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

时间:2012-05-04 10:54:04

标签: 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   |
+----------+------------+    +-----------+------------+    +--------+--------+

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

+--------+---------------+----------------+
|   id   |    country    |   match_count  |
+--------+---------------+----------------+
|    6   |      gb       |       4        |
|    9   |      gb       |       4        |
|    2   |      gb       |       3        |
|    1   |      gb       |       2        |
|    5   |      gb       |       0        |
|    4   |      gb       |       0        |
+--------+---------------+----------------+

我一直在尝试使用子查询来获取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;

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

1 个答案:

答案 0 :(得分: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;

假设您有一个favourite_artists(user_id)的索引 - 或者更好的是multi-column index favourite_artists(user_id, artist_id),此查询将更有效地获取加入的行。