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_idPRIMARY KEY,那么你需要升级PostgreSQL; 新版本将正确处理主键的分组。

如果user_id既不是唯一的也不是唯一的, 而且这个查询没有什么意义,因为PostgreSQL没有办法知道在多行共享相同estates每一列的情况下返回哪个user_id 。 你必须使用expression你想要的东西的集合函数,比如minmaxavgstring_aggarray_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)") 

这是我做的。