Rails where和group子句

时间:2016-01-22 09:03:05

标签: ruby-on-rails postgresql

我收集了Cost条记录,并希望选择特定费用并按天分组

我试过这个

 @costs = Cost.where(source:(params[:source]),month:params[:month]).group(:day).order('created_at ASC')

但在此之后我得到ActiveRecord::StatementInvalid: PG::GroupingError: ERROR: column "costs.id" must appear in the GROUP BY clause or be used in an aggregate function

我的目标是获取特定记录并按天分组

例如我有少量记录15月1日我可以在这一天添加多条记录,所以我需要将它们组合在一起

或者您可以建议任何其他解决方案

db - psql (PostgreSQL) 9.4.5

rails - Rails 4.2.5

3 个答案:

答案 0 :(得分:2)

如果要使用group,则必须在组上添加一种计算或聚合函数。要获取分组记录,请先尝试获取分组ID,然后只能获取具有给定ID的记录:

groups = Cost.group(:day).select('array_agg(id) as ids, day').limit(100).to_a
last_day_group = groups.last

# now you can get ids array and day value
puts last_day_group.day
 # => 'Monday'
puts last_day_group.ids
 # => [1, 2, 3, 45]

# get Cost records by day: 
Cost.where(id: last_day_group.ids)

答案 1 :(得分:1)

这是因为您以错误的方式使用该组。您上面的代码将由Rails翻译成sql语句,即

select * from cost where source = value and month = value group by day order by created_at asc

这是一个无效的sql语句,因为您正在选择表中的所有字段,并且它们都不属于任何聚合函数或group by子句。

请查看此link以获取有关如何编写正确的分组条款的详细信息。

这是一个正确转换为sql语句的Rails代码示例,其中包含group by子句的用法。

Order.select("COUNT(id) as num, payment_method, purchase_price, selling_price, xcount").where("multiplex_id = ? AND created_at >= ? AND created_at <= ? AND state = ?", multiplex_id, start_date, end_date, 'reserved').group(:payment_method, :purchase_price, :selling_price, :xcount)

如您所见,我已指定了我需要检索的所有字段,所有这些字段都是聚合函数的一部分或由group by子句使用。

答案 2 :(得分:0)

您可能会混淆ActiveRelation#group这是一个SQL子句而Array#group_by会根据一个值对数组的块进行分组。因此,在您的情况下,您只需要以这种方式重写它:

# in your controller 
@costs = Cost.where(source:(params[:source]),month:params[:month]).order('created_at ASC')

# in your view
- @costs.group_by(&:date) do |date, n_costs|
  = date
  - n_costs.compact.each do |cost|
    %p= cost.source
    # etc

这是nice tutorial