Postgresql查询 - 按子查询的结果排序

joh*_*ire 7 sql postgresql join subquery

我有一个查询,我想选择所有喜欢给定艺术家的用户.国家等也有其他一些WHERE标准.这是模式的样子.

          users                     favourite_artists             artists

+----------+------------+    +-----------+------------+    +--------+--------+
|    id    |  country   |    |  user_id  |  artist_id |    |  id    |  name  |
+----------+------------+    +-----------+------------+    +--------+--------+
|     1    |     gb     |    |     1     |      6     |    |   1    |  Muse  |
|     2    |     gb     |    |     1     |      5     |    |   2    |  RATM  |
|     3    |     us     |    |     1     |      3     |    |   3    |  ABBA  | 
|     4    |     us     |    |     2     |      3     |    |   4    |   U2   |
+----------+------------+    +-----------+------------+    +--------+--------+
Run Code Online (Sandbox Code Playgroud)

我想按他们喜欢的那些艺术家的数量订购.我还希望包括那些不喜欢任何艺术家但符合WHERE标准的用户.预期的结果集看起来像.

+--------+---------------+----------------+
|   id   |    country    |   match_count  |
+--------+---------------+----------------+
|    6   |      gb       |       4        |
|    9   |      gb       |       4        |
|    2   |      gb       |       3        |
|    1   |      gb       |       2        |
|    5   |      gb       |       0        |
|    4   |      gb       |       0        |
+--------+---------------+----------------+
Run Code Online (Sandbox Code Playgroud)

我一直在尝试使用子查询来获取match_count并按顺序排序,但它的执行速度非常慢所以我认为必须有更好的方法.

   SELECT users.id, users.country
   (SELECT COUNT(*) FROM favourite_artists 
    WHERE user_id = users.id AND artist_id IN (1,3,4,9)) AS match_count        
   FROM "users" 
   WHERE users.country = 'gb'
   ORDER BY match_count DESC;
Run Code Online (Sandbox Code Playgroud)

我正在使用Postgresql 9.0.7.有什么想法吗?

Boh*_*ian 6

您的查询正在为每行执行一个子查询users.这样的查询称为" 相关子查询 ",它们的性能很可取,很可取.

相反,你想要一个加入:

SELECT users.id, users.country, count(artist_id) as match_count
FROM users
LEFT JOIN favourite_artists ON user_id = users.id AND artist_id IN (1,3,4,9)
WHERE users.country = 'gb'
GROUP BY 1, 2
ORDER BY 3 DESC;
Run Code Online (Sandbox Code Playgroud)

假设您有索引favourite_artists(user_id)- 或者更好的是多列索引 ,此查询将更有效地获取加入行favourite_artists(user_id, artist_id).

  • 我的内裤不是一堆.我只是认为这种做法很糟糕**依赖于数字位置指示器1)在指定字段名称和2)字段的顺序同样简单和清晰时,在SQL语言的支持下,违反了关系模型.开始一场战争并不是一件足够大的交易.我只是提出它作为一个有用的建议. (5认同)
  • 依赖ORDER BY子句中的位置违反了关系理论,后者认为不确定结果集中字段的顺序。我建议改为“ ORDER BY match_count”。 (2认同)