PG:GroupingError仅出现在制作

时间:2015-11-12 09:08:25

标签: sql ruby-on-rails ruby postgresql inner-join

我有一个模特"播放列表" has_many和belongs_to另一个模型" User",通过中间模型" PlaylistUser"。

我的代码是,对于给定的播放列表@playlist,列出与@playlist共享用户的所有其他播放列表,按其共享的数量排序。

此代码完全适用于开发,但在生产时,它会抛出此错误:

PG::GroupingError: ERROR:  column "playlists.name" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "playlists".* FROM "playlists" INNER JOIN "playlist...
           ^
: SELECT "playlists".* FROM "playlists" INNER JOIN "playlist_users" ON "playlist_users"."playlist_id" = "playlists"."id" INNER JOIN "users" ON "users"."id" = "playlist_users"."user_id" WHERE (NOT (playlists.id = 30 OR playlists.id = 41)) AND "users"."id" IN (45, 89, 71, 117, 115, 173, 177, 180, 161, 220, 223, 199, 221, 239, 204, 205, 206, 207, 211, 261, 282, 284, 286, 251, 252, 255, 310, 311, 315, 318, 307, 362, 319, 306, 289, 316, 305, 321, 322, 330, 333, 292, 294, 304, 300, 340, 341, 342, 343, 405, 406, 410, 408, 409, 407, 413, 416, 417, 418, 425, 427, 392, 401, 403, 445, 446, 449, 450, 379, 456, 451, 454, 459, 437, 442, 444, 496, 501, 518, 548, 549, 533, 553, 1112, 1113, 1459, 455, 348, 1458, 242, 1275, 151, 1890, 336, 203, 404, 166, 453, 114, 157, 285, 448, 447, 443, 550, 2167, 2168, 287, 320, 293, 65, 2098, 2097, 2099, 387, 3, 2175, 2170, 2174, 2182, 2171, 438, 2180, 2181, 2169, 2176, 347, 2429, 2177, 2445, 2178, 2447, 58, 2480, 390, 452, 554, 555, 313, 92, 275, 335, 428, 167, 302, 2173, 1538) GROUP BY playlists.id  ORDER BY count(*) desc

为什么我的查询会处理开发而不是生产?

查询

@playlist_ids = @playlist.user_ids
@more_playlists = Playlist.joins(:users).where.not('playlists.id = ? OR playlists.id = ?', 30, 41).where(users: {id: @playlist_ids}).group('playlists.id').order('count(*) desc')

关联设定:

class Playlist < ActiveRecord::Base
  has_many :playlist_users
  has_many :users, :through => :playlist_users
end

class PlaylistUser < ActiveRecord::Base
  belongs_to :playlist
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :playlist_users
  has_many :playlists, :through => :playlist_users
end

更新

这很奇怪,我按照trincot的建议将Playlist.name添加到GROUP BY:

@playlist_ids = @playlist.user_ids
Playlist.select('playlists.id, playlists.name')
    .joins(:playlist_users)
    .where('playlists.id NOT IN (30, 41)')
    .where(playlist_users: {user_id: @playlist_ids})
    .group('playlists.id, playlists.name')
    .order('count(*) desc')

但是我收到了类似的错误,除非它现在告诉我必须在GROUP BY子句中包含Playlist属性subject_id

PG::GroupingError: ERROR:  column "playlists.subject_id" must appear in the GROUP BY clause or be used in an aggregate function

但我没有在我的查询中的任何地方引用subject_id,甚至在页面的模型,控制器或视图中引用git config -l。为什么该专栏甚至会参与其中呢?

1 个答案:

答案 0 :(得分:1)

根据PostgreSQL documentation

,您的陈述无效
  

当GROUP BY存在时,它对SELECT列表表达式无效   除了聚合函数之外的未分组列,因为会有多个列   为未分组的列返回的可能值。

如果您说它在您的开发环境中有效,那么它必须意味着环境中有另一个数据库引擎(版本)正在运行。

你应该使用这样的语句,其中SELECT子句中的字段列表与GROUP BY子句中给出的列表相同:

SELECT      playlists.id,  playlists.name, ...
FROM        playlists 
INNER JOIN  playlist_users ON playlist_users.playlist_id = playlists.id 
WHERE       playlists.id NOT IN (30, 41) 
AND         playlist_users.user_id IN (your_long_list_comes_here) 
GROUP BY    playlists.id,  playlists.name, ...
ORDER BY    count(*) desc

请注意,您实际上并不需要加入用户表以获取您感兴趣的结果,因此我将其删除并相应地替换了 user_id 上的测试。此外,playlists.id上的条件使用IN运算符表示得更简洁。

相应的Active Record查询将是:

Playlist.joins(:playlist_users)
    .where('playlists.id NOT IN (30, 41)')
    .where(playlist_users: {user_id: @playlist_ids})
    .select('playlists.id, playlists.name')
    .group('playlists.id, playlists.name')
    .order('count(*) desc')

您必须在selectgroup参数中添加所需的任何其他字段。