PostgreSQL - 必须出现在 GROUP BY 子句中或在聚合函数中使用

Posted

技术标签:

【中文标题】PostgreSQL - 必须出现在 GROUP BY 子句中或在聚合函数中使用【英文标题】:PostgreSQL -must appear in the GROUP BY clause or be used in an aggregate function 【发布时间】:2013-08-06 08:16:01 【问题描述】:

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

【问题讨论】:

在 PostgreSQL 中使用 GROUP BY,如果您没有在 group by 中使用它,则不能使用选择列表中的列。不知道怎么翻译成rails 相关:***.com/q/19601948/398670 可能重复:***.com/questions/19601948/… 【参考方案1】:

如果user_id主键 那么你需要升级PostgreSQL;较新的版本将正确处理按主键分组。

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

或者,如果您确实想选择任意行,您也可以改写查询以使用 DISTINCT ONORDER 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 的结果呢?没有单一的正确答案可供选择,因此数据库将拒绝执行此类不安全的查询。如果您希望任何col1最大 col2,您可以使用max 聚合:

SELECT col1, max(col2) AS max_col2 FROM mytable GROUP BY col1;

【讨论】:

user_id 是 User 表中的主键,但在 Estate 表中是主键。 @HrishikeshSardar 在这种情况下,此查询没有意义。对于任何给定的user_id,它会返回哪个 Estate?随便挑一个?它不会那样做。您必须使用汇总或重新考虑您在做什么。 我想弄清楚我是否有 @estate 的值像 1,1,2,3,4,5,6,6,但现在我只想要 1, 2,3,4,5,6,我该怎么办,在这个例子中我给了 ua 数组,但我想要哈希数组也一样 我将如何翻译这个查询“SELECT col1, max(col2) AS max_col2 FROM mytable GROUP BY col1;”进入红宝石? @HrishikeshSardar api.rubyonrails.org/classes/ActiveRecord/Calculations.html 。奇怪的是,"activerecord max" 在 Google 中的第一次点击。【参考方案2】:

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

Elegant PostgreSQL Group by for Ruby on Rails / ActiveRecord

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

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

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

【讨论】:

DISTINCT ON 在适当的时候很有用。但是查询计划器在使用DISTINCT ON 时不如使用DISTINCTGROUP BY 智能,因此除非您确实需要,否则值得避免使用它。这也是非标准的。【参考方案3】:

在我自己经常收到错误后,我意识到 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')

【讨论】:

我有相同的(订购我的模型的默认范围)。所以我所做的是:Model.reorder(nil).group_by(...) 这样订单就被删除了。 这条评论...应该是答案。【参考方案4】:
@myestate1 = Estate.where(:Mgmt => current_user.Company)
@myestate = @myestate1.select("DISTINCT(user_id)")

这就是我所做的。

【讨论】:

以上是关于PostgreSQL - 必须出现在 GROUP BY 子句中或在聚合函数中使用的主要内容,如果未能解决你的问题,请参考以下文章

Postgresql 错误:列必须出现在 GROUP BY 子句中或在聚合函数中使用

Django 与 Postgresql,列必须出现在 GROUP BY 子句中或在聚合函数中使用

Postgresql“列必须出现在 GROUP BY 子句中或在聚合函数中使用”和唯一字段

Postgresql 9.2 错误与 group by 未出现在 postgresql 12 中

postgreSQL使用sql归一化数据表的某列,以及出现“字段 ‘xxx’ 必须出现在 GROUP BY 子句中或者在聚合函数中”错误的可能原因之一

PostgreSQL GROUP BY LOWER() 不工作