Postgres 查询在控制台上工作,但将其用作视图中的范围会呈现语法错误

Posted

技术标签:

【中文标题】Postgres 查询在控制台上工作,但将其用作视图中的范围会呈现语法错误【英文标题】:Postgres query works on console but using it as a scope in a view renders syntax errors 【发布时间】:2022-01-02 02:33:13 【问题描述】:

我正在使用查询从Subscription 中获取具有最早authorized_at 日期的SubscriptionCart

由于Subscription has_many SubscriptionCart,我使用与订阅plan_id 相同的plan_id 过滤购物车。我还将WHERE 语句用于SubscriptionSubscriptionCart 状态。

查询似乎在控制台上运行良好,但是当我将它放入订阅范围并尝试在我的视图中使用它时,我得到:

PG::SyntaxError: ERROR:  syntax error at or near "WHERE"
LINE 6: ...ubscriptions.id, subscription_carts.authorized_at WHERE "sub...

发生了什么事?

查询:

select distinct on (s.id) s.id, sc.authorized_at as cart_authorized_at, s.*
from subscriptions s
join subscription_carts sc on sc.subscription_id = s.id and sc.plan_id = s.plan_id
where sc.status = 'processed'
and s.status IN ('authorized','in_trial', 'paused')
order by s.id, sc.authorized_at

范围:

  scope :with_current_price_version, -> 
    select("
      DISTINCT ON (subscriptions.id) subscriptions.id,
      subscription_carts.authorized_at as version_cart_authorized_at,
      subscriptions.*
    ")
    .joins("
      INNER JOIN subscription_carts
      ON subscription_carts.subscription_id = subscriptions.id                 
      AND subscription_carts.plan_id = subscriptions.plan_id   
      WHERE subscription_carts.status = 'processed'
      AND subscriptions.status IN ('authorized','in_trial', 'paused')
      ORDER BY subscriptions.id, subscription_carts.authorized_at
    ")
  

编辑:将 WHERE、AND 和 ORDER BY 子句移到 .join 之外解决了这个问题。

更新后的范围如下:

  scope :with_current_price_version, -> 
    select("DISTINCT ON (subscriptions.id) subscriptions.id,
           subscription_carts.authorized_at as version_cart_authorized_at, subscriptions.*")
      .joins("INNER JOIN subscription_carts on subscription_carts.subscription_id = subscriptions.id
             AND subscription_carts.plan_id = subscriptions.plan_id")
      .where("subscription_carts.status = 'processed'
             AND subscriptions.status IN ('authorized','in_trial', 'paused')")
      .order("subscriptions.id, subscription_carts.authorized_at")
  

【问题讨论】:

您可以尝试将joins 方法中的WHEREANDORDER BY 部分移出它。它可能无法正常工作,但您将整个查询添加到 joins 方法中,乍一看似乎令人困惑。 很好,我只是想在本地复制你的问题。 【参考方案1】:
class Subscription < ApplicationRecord
  def self.with_latest_subscription_cart
    s = arel_table
    sc = SubscriptionCart.arel_table.alias('sc')
    select(
      'DISTINCT ON(subscriptions.id)',
      :id, # not sure why you want to select this explicitly 
      s[Arel.star],
      sc[:authorized_at]
    )
    .joins(
      s.join(sc).on(
        sc[:subscription_id].eq(s[:id]).and(
          sc[:plan_id].eq(s[:plan_id])
        )
      ).join_sources
    )
    .where(
      status: 'processed',
      sc: 
        status: ['authorized','in_trial', 'paused']
      
    )
    .order(:id, sc[:authorized_at])
  end
end

如果您将subscription_carts.plan_id = subscriptions.plan_id 移到WHERE 子句中,这样您就可以使用joins(:subscription_carts),这会容易得多。

【讨论】:

谢谢马克斯。有没有办法按authorized_at 日期而不是按subscription.id 订购?我收到一个与 distinct on 和 order by 表达式不同有关的错误。 我可能会使用横向连接 - 请参阅我对您其他问题的回答。

以上是关于Postgres 查询在控制台上工作,但将其用作视图中的范围会呈现语法错误的主要内容,如果未能解决你的问题,请参考以下文章

从 git 分支中删除文件但将其保留在另一个?

在 AWS lambda Web 控制台上测试 Apollo graphql 查询

是否可以在 Postgres 中执行并行查询,使用 union all 查询分区表?

T-SQL 谜题:将其用作内联视图时查询失败

如何在构建时忽略 .sql 文件,但将其包含在架构比较中

从存储库中删除文件但将其保留在本地