PostgreSQL – 必须出现在GROUP BY子句中或用于聚合函数中
我在pg生产模式中得到这个错误,但它在sqlite3开发模式下工作正常。
ActiveRecord::StatementInvalid in ManagementController#index PG::Error: ERROR: column "estates.id" must appear in the GROUP BY clause or be used in an aggregate function LINE 1: SELECT "estates".* FROM "estates" WHERE "estates"."Mgmt" = ... ^ : SELECT "estates".* FROM "estates" WHERE "estates"."Mgmt" = 'Mazzey' GROUP BY user_id @myestate = Estate.where(:Mgmt => current_user.Company).group(:user_id).all
如果user_id
是PRIMARY KEY,那么你需要升级PostgreSQL; 新版本将正确处理主键的分组。
如果user_id
既不是唯一的也不是唯一的, 而且这个查询没有什么意义,因为PostgreSQL没有办法知道在多行共享相同estates
每一列的情况下返回哪个值user_id
。 你必须使用expression你想要的东西的集合函数,比如min
, max
, avg
, string_agg
, array_agg
等,或者把感兴趣的列添加到GROUP BY
。
或者,如果你真的想要select一个有点任意的行,你可以改写查询使用DISTINCT ON
和一个ORDER BY
,但我真的怀疑可以通过ActiveRecord来expression。
一些数据库(包括SQLite和MySQL)只会select一个任意的行。 这被认为是不正确的,PostgreSQL团队不安全,所以PostgreSQL遵循SQL标准,并认为这样的查询是错误的。
如果你有:
col1 col2 fred 42 bob 9 fred 44 fred 99
你做:
SELECT col1, col2 FROM mytable GROUP BY col1;
那么显然你应该得到这一行:
bob 9
但是fred
的结果呢? 没有一个正确的答案select,所以数据库将拒绝执行这样的不安全的查询。 如果你想要col1
最棒的 col2
,你可以使用max
聚合:
SELECT col1, max(col2) AS max_col2 FROM mytable GROUP BY col1;
我最近从MySQL迁移到PostgreSQL,遇到了同样的问题。 仅供参考,我发现的最佳方法是使用DISTINCT ON,正如在这个答案中所build议的那样:
用于Ruby on Rails / ActiveRecord的优雅的PostgreSQL Group
这样可以让您为选定的列中每个与其他查询条件匹配的唯一值logging一条logging:
MyModel.where(:some_col => value).select("DISTINCT ON (unique_col) *")
我更喜欢DISTINCT ON,因为我仍然可以获取行中的所有其他列值。 仅DISTINCT将只返回该特定列的值。
自己经常收到错误后,我意识到Rails(我正在使用rails 4)在分组查询结束时自动添加“按IDsorting”。 这往往会导致上述错误。 所以确保你在你的Rails查询结尾追加你自己的.order(:group_by_column)。 因此,你会有这样的事情:
@problems = Problem.select('problems.username, sum(problems.weight) as weight_sum').group('problems.username').order('problems.username')
@myestate1 = Estate.where(:Mgmt => current_user.Company) @myestate = @myestate1.select("DISTINCT(user_id)")
这是我做的。