8

特定のアーティストのセットが好きなすべてのユーザーを選択するクエリがあります。国などには、他にもいくつかの 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 を使用しています。何かご意見は?

4

1 に答える 1

10

あなたのクエリは、 のすべての行に対して 1 つのサブクエリを実行してい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)このクエリは、複数列のインデックス にインデックスがあると仮定すると、結合行をはるかに効率的に取得しますfavourite_artists(user_id, artist_id)

于 2012-05-04T11:04:43.917 に答える