【问题标题】:Converting SQL to Arel - column [...] must appear in the GROUP BY clause将 SQL 转换为 Arel - 列 [...] 必须出现在 GROUP BY 子句中
【发布时间】:2018-11-26 08:48:32
【问题描述】:

我有一个有效的 SQL 查询,我想将其转换为 Arel,但我似乎一直遇到同样的错误。

工作 SQL:

Order.find_by_sql(
    "SELECT COUNT(order_number) AS order_count,
    restaurant_id, date_part('month', date) AS date_month,
    date_part('year', date) AS date_year 
    FROM orders
    WHERE restaurant_id is not null
    GROUP BY(restaurant_id, date_part('month', date), date_part('year', date))
    ORDER BY date_part('year', date) desc, date_part('month', date) desc;"
  )

尝试 1(不工作)

orders = Order.arel_table

Order
    .where.not(restaurant_id: nil)
    .select(:restaurant_id)
    .select(:date)
    .select(Order.arel_table[:order_number].count.as('order_count'))
    .select(
        Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), :date]),
        Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
    )
    .group(
        :restaurant_id, 
        Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]), 
        Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
    )

尝试 2(不工作)

orders = Order.arel_table
query = orders
      .where(orders[:restaurant_id].not_eq(nil))
      .project(
          orders[:restaurant_id],
          Order.arel_table[:order_number].count.as('order_count'),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
      )
      .group(
          orders[:restaurant_id],
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
      )
      .order(orders[:date].desc)
      .to_sql
Order.find_by_sql(query)

这两种方法都会导致以下错误:

PG::GroupingError: ERROR: column "orders.date" 必须出现在 GROUP BY 子句中或用于聚合函数中

问题是我不想按日期分组,而是按月份分组。有什么解决办法吗?

我最初也尝试过Arel::Nodes::NamedFunction.new('date_part', ['month', :date]) 而不是Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),但结果如下:

不支持的参数类型:字符串。而是构建一个 Arel 节点。

非常感谢任何帮助。谢谢!

【问题讨论】:

    标签: postgresql arel


    【解决方案1】:

    因此,经过数小时的挖掘,事实证明这是个大问题!我的问题是在我的Order 模型上设置了default_scope - 这就是按:date 进行排序的地方。最后,我决定删除默认范围,在实际需要的地方使用排序,而我的查询剩下的是:

    orders = Order.arel_table
    query = orders
      .where(orders[:restaurant_id].not_eq(nil))
      .project(
          orders[:restaurant_id],
          Order.arel_table[:order_number].count.as('order_count'),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]).as('date_month'),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]]).as('date_year'),
      )
      .group(
          orders[:restaurant_id],
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), orders[:date]]),
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), orders[:date]])
      )
      .order(
          orders[:restaurant_id],
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('year'), date]).desc,
          Arel::Nodes::NamedFunction.new('date_part', [Arel::Nodes.build_quoted('month'), date]).desc
    
      )
      .to_sql
    
    Order.find_by_sql(query)
    

    经验教训:尽可能避免default_scopes。如果您独自工作,您可能会随着时间的推移忘记使用它。如果你在一个团队中工作,你可能只会花掉某人一整天的时间。

    【讨论】:

      猜你喜欢
      • 2016-05-26
      • 2015-04-20
      • 2016-04-03
      • 2020-02-08
      • 1970-01-01
      • 1970-01-01
      • 2015-08-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多