4

I'm using this method:

  def self.lines_price_report(n)
    Income.group('date(filled_at)').having("date(filled_at) > ?", Date.today - n).sum(:lines_price)
  end

I'm getting this error in Heroku:

PG::Error: ERROR:  column "incomes.filled_at" must appear in the GROUP BY clause 
or be used in an aggregate function

How can I fix this? Thank you.

Executed query:

SELECT SUM("incomes"."lines_price") AS sum_lines_price, date(filled_at)
AS date_filled_at FROM "incomes"
HAVING (date(filled_at) > '2012-12-04')
GROUP BY date(filled_at) ORDER BY filled_at ASC

Expected result

[["2012-12-04", SUM_FOR_DATE], ["2012-12-05", SUM_FOR_DATE], ...]
4

3 回答 3

6

您的错误是在默认范围内按顺序使用 fill_at 。

您可以使用 unscoped 修复它以消除默认范围:

Income.unscoped
 .group('date(filled_at)')
 .having("date(filled_at) > ?", Date.today - n)
 .sum(:lines_price)

或者

Income.unscoped
   .group('date(filled_at)')
   .having("date(filled_at) > ?", Date.today - n)
   .sum(:lines_price)
   .order('date(filled_at) ASC')

但我认为最好使用 where 而不是拥有

Income.unscoped
  .where("date(filled_at) > TIMESTAMP ?", Date.today - n)
  .group('date(filled_at)')
  .sum(:lines_price)
  .order('date(filled_at) ASC')

SQLFiddle

你必须小心使用 TIMESTAMP 因为 2012-12-04 将变为 2012-12-04 00:00:00 所以如果你不希望这一天在结果中使用 Date.today - (n - 1)

如果您在filled_at 列上创建索引

 create index incomes_filled_at on incomes(filled_at);

移民:

 add_index :incomes, :filled_at

而且你有很多数据在这个表索引中会用到过滤。所以查询应该快得多。

因此,只需编写两者并测试哪个更快(如果没有,则必须在filled_at 上创建索引)。

于 2012-12-18T12:56:33.270 回答
3

我想这是因为您date(filled_at)在 GROUP BY 中使用但只是filled at在 ORDER 中使用。因为我猜 order 是从默认范围中获取的,所以您需要将其覆盖为reorder. 我会建议:

Income.sum(:lines_price).
    group('date(filled_at)').
    having("date(filled_at) > ?", Date.today - n).
    reorder("date(filled_at) ASC")
于 2012-12-18T12:41:18.280 回答
1

当你想在 PostgreSQL 上使用 Group By 时,在 group by 上应该需要 select 选项。

Income.select('filled_at').group('date(filled_at)').having("date(filled_at) > ?", Date.today - n).sum(:lines_price)
于 2013-05-20T22:32:45.757 回答