在SQLite和Postgres中的Rails Active Record组查询

时间:2017-04-27 02:13:49

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

在SQLite中使用Active Record运行查询时遇到错误。 Postgres中存在聚合函数错误,但SQLite中没有任何错误。我的问题是,SQLite在这做什么?它是否忽视了这个群体?请注意GROUP BY" song"不会返回错误。

SQLite输出:

Playlist.where(USER_ID:user.id)。集团(:曲)

$html = <<<HTML
<html>
<head>
<title>Example</title>
</head>
<body>
<a href='link1.php'>Link</a>
<a href="link's 2.php" class="link">Link2</a>
<a class="link" href='link3.php' rel='nofollow'>Link3</a>
<a href='link4.php'><span>Link4</span></a>
</body>
</html>
HTML;

$doc = new DOMDocument();
$valid = $doc->loadHTML($html);
$result = [];
if ($valid) {
  $xpath = new DOMXpath($doc);
  // find any <a> elements that do not have a rel="nofollow" attribute,
  // then pick up their href attribute
  $elements = $xpath->query("//a[not(@rel='nofollow')]/@href");
  if (!is_null($elements)) {
    foreach ($elements as $element) {
      $result[] = $element->nodeValue;
    }
  }
}
print_r($result);
# => Array
#    (
#        [0] => link1.php
#        [1] => link's 2.php
#        [2] => link4.php
#    )

Playlist.where(USER_ID:user.id)。集团(:song_id)

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)。集团(:ID,: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)。集团(:曲).Count之间的

 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">]> 

Postgres的:

Playlist.where(USER_ID:user.id)。集团(:song_id)

 (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}

Playlist.where(USER_ID:user.id)。集团(:ID,: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)。集团(:曲).Count之间的

 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">]>

1 个答案:

答案 0 :(得分:0)

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