28

我在 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
4

4 回答 4

47

如果user_idPRIMARY KEY则需要升级 PostgreSQL;较新的版本将正确处理按主键进行的分组。

如果对于所讨论的 'estates' 关系user_id既不是唯一的也不是主键,那么这个查询没有多大意义,因为 PostgreSQL 无法知道为多行共享相同的每一列返回哪个值。您必须使用一个聚合函数来表达您想要的内容,例如, , , ,等,或者将感兴趣的列添加到.estatesuser_idminmaxavgstring_aggarray_aggGROUP BY

或者,您可以改写要使用的查询,DISTINCT ON如果ORDER BY您真的想选择一个有点随意的行,尽管我真的怀疑是否可以通过 ActiveRecord 表达这一点。

一些数据库——包括 SQLite 和 MySQL——只会选择任意行。PostgreSQL 团队认为这不正确且不安全,因此 PostgreSQL 遵循 SQL 标准并将此类查询视为错误。

如果你有:

col1    col2
fred    42
bob     9
fred    44
fred    99

你也是:

SELECT col1, col2 FROM mytable GROUP BY col1;

那么很明显你应该得到该行:

bob     9

但是结果fred呢?没有单一的正确答案可供选择,因此数据库将拒绝执行此类不安全的查询。如果您想要任何最大 的,您将使用聚合:col2col1max

SELECT col1, max(col2) AS max_col2 FROM mytable GROUP BY col1;
于 2013-08-05T15:04:34.747 回答
16

我最近从 MySQL 迁移到 PostgreSQL 并遇到了同样的问题。仅供参考,我发现的最佳方法是按照此 SO 答案中的建议使用 DISTINCT ON :

优雅的 PostgreSQL Group by for Ruby on Rails / ActiveRecord

这将让您为所选列中与其他查询条件匹配的每个唯一值获取一条记录:

MyModel.where(:some_col => value).select("DISTINCT ON (unique_col) *") 

我更喜欢 DISTINCT ON,因为我仍然可以获得行中的所有其他列值。单独的 DISTINCT 只会返回该特定列的值。

于 2013-11-27T10:11:28.010 回答
6

在我自己经常收到错误后,我意识到 Rails(我使用的是 rails 4)会在分组查询的末尾自动添加一个“order by id”。这通常会导致上述错误。因此,请确保在 Rails 查询的末尾附加您自己的 .order(:group_by_column) 。因此你会有这样的东西:

@problems = Problem.select('problems.username, sum(problems.weight) as weight_sum').group('problems.username').order('problems.username')
于 2015-01-02T06:58:02.793 回答
3
@myestate1 = Estate.where(:Mgmt => current_user.Company)
@myestate = @myestate1.select("DISTINCT(user_id)")

这就是我所做的。

于 2013-08-05T15:54:38.693 回答