【问题标题】:Rails Active Record group query in SQLite vs PostgresSQLite 与 Postgres 中的 Rails Active Record 组查询
【发布时间】:2017-09-24 15:28:12
【问题描述】:

在使用 Active Record 在 SQLite 与 Postgres 中运行查询时出现错误。 Postgres 中存在聚合函数错误,但 SQLite 中没有。我的问题是,SQLite 在这里做什么?是无视群吗?请注意,GROUP BY "song" 不会返回错误。

SQLite 输出:

Playlist.where(user_id:user.id).group(:song)

Playlist Load (0.3ms)  SELECT "playlists".* FROM "playlists" WHERE 
"playlists"."user_id" = ? GROUP BY "song"  [["user_id", 1]]

=> #<ActiveRecord::Relation [#<Playlist id: 2, user_id: 1, song_id: 1, 
created_at: "2017-04-27 01:18:01", updated_at: "2017-04-27 01:18:01">]>

Playlist.where(user_id:user.id).group(:song_id)

 Playlist Load (0.4ms)  SELECT "playlists"."id", "playlists"."user_id",
 "playlists"."song_id" FROM "playlists" WHERE "playlists"."user_id" = ?
 GROUP BY "song"  [["user_id", 1]]

  => #<ActiveRecord::Relation [#<Playlist id: 2, user_id: 1, song_id: 
  1, created_at: "2017-04-27 01:18:01">]>

Playlist.where(user_id:user.id).group(:id,:song_id)

 Playlist Load (0.2ms)  SELECT "playlists".* FROM "playlists" WHERE 
 "playlists"."user_id" = ? GROUP BY "playlists"."id", 
 "playlists"."song_id"  [["user_id", 1]]

 => #<ActiveRecord::Relation [#<Playlist id: 1, user_id: 1, song_id: 1, 
 created_at: "2017-04-27 01:18:00", updated_at: "2017-04-27 01:18:00">, 
 #<Playlist id: 2, user_id: 1, song_id: 1, created_at: "2017-04-27 
 01:18:01", updated_at: "2017-04-27 01:18:01">]> 

Playlist.where(user_id:user.id).group(:song).count

 (0.2ms)  SELECT COUNT(*) AS count_all, "playlists"."song_id" AS      
 playlists_song_id FROM "playlists" WHERE "playlists"."user_id" = ? 
 GROUP BY "playlists"."song_id"  [["user_id", 1]]

 Song Load (2.1ms)  SELECT  "songs".* FROM "songs" 
 WHERE "songs"."id" = ? LIMIT 1  [["id", 1]] 

 => {#<Song id: 1, title: "A song", artist: "Artist", user_id: 1, 
 created_at: "2017-04-27 01:17:39">=>2}

Postgres:

Playlist.where(user_id:user.id).group(:song_id)

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

SELECT "playlists".* FROM "playlists" WHERE "playlists"."user_id" = $1 
GROUP BY "playlists"."song_id"

Playlist.where(user_id:user.id).group(:id,:song_id)

 Playlist Load (0.6ms)  SELECT "playlists".* FROM "playlists" WHERE 
 "playlists"."user_id" = $1 GROUP BY "playlists"."id",      
 "playlists"."song_id"  [["user_id", 1]]

 => #<ActiveRecord::Relation [#<Playlist id: 1, user_id: 1, song_id: 1, 
 created_at: "2017-04-27 01:25:34", updated_at: "2017-04-27 01:25:34">, 
 #<Playlist id: 2, user_id: 1, song_id: 1, created_at: "2017-04-27 
 01:25:36", updated_at: "2017-04-27 01:25:36">]>

Playlist.where(user_id:user.id).group(:song).count

 (0.5ms)  SELECT COUNT(*) AS count_all, "playlists"."song_id" AS 
 playlists_song_id FROM "playlists" WHERE "playlists"."user_id" = $1 
 GROUP BY "playlists"."song_id"  [["user_id", 1]]

 Song Load (0.3ms)  SELECT  "songs".* FROM "songs" WHERE "songs"."id" = 
 $1 LIMIT 1  [["id", 1]]

 => {#<Song id: 1, title: "A song", artist: "Artist", user_id: 1, 
 created_at: "2017-04-27 01:25:26", updated_at: "2017-04-27           
 01:25:26">=>2}

【问题讨论】:

  • 我查看了其他问题,但我的问题更关注 SQLite 在做什么以及为什么要做它正在做的事情。它似乎忽略了 SQL 语句的 group 子句。我没有提到任何关于部署的事情。我只是在开发过程中切换到 Postgres,因为我忘了给它在 rails new 上的 Postgres 标志。我在问题中也有适当的聚合查询。

标签: sql ruby-on-rails postgresql sqlite activerecord


【解决方案1】:

group by 的通用规则:您只能选择group by 中列出的列和聚合函数。此方法受 sql 标准支持,适用于任何 sql 数据库。

如果您选择group by 子句中未列出的列,例如select * … group by song_id,它可能在某些数据库中有效,而在其他数据库中无效。

如果您在代码中指定选定的列,它将起作用:

Playlist.
  where(user_id:user.id).
  select("song_id").
  group(:song_id)

您可以在 PostgreSQL 文档中阅读有关 group by 的详细信息:https://www.postgresql.org/docs/current/static/sql-select.html#SQL-GROUPBY

【讨论】:

    猜你喜欢
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多