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.有什么想法吗?
您的查询正在为每行执行一个子查询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).