サブクエリは、次の2つのタイプに分類できます:
- 非相関(単純な)サブクエリは、それを含む(外側の)ステートメントとは無関係にその結果を取得します。
- 相関サブクエリは、実行のためにその外側のクエリから値を参照します。
非相関サブクエリが(外側のクエリとは無関係に)実行されると、サブクエリが最初に実行され、次にその結果が外側のクエリに渡されます。一方、相関サブクエリは通常、実行前にその外側のクエリから値を取得します。サブクエリが戻ると、その結果が外側のクエリに渡されます。
相関サブクエリと非相関サブクエリの違いがわかったので、このブログでは、Navicat Premium 16で相関サブクエリを作成する方法について説明します。
構文と使用法
相関サブクエリは、親ステートメントによって処理される行ごとに1回評価されます。親ステートメントは、SELECT、UPDATE、またはDELETEステートメントにすることができます。SELECTクエリの構文は次のとおりです:
SELECT column1, column2, .... FROM table1 outer WHERE column1 operator (SELECT column1, column2 FROM table2 WHERE expr1 = outer.expr2);
相関サブクエリは、テーブル内の全ての行を読み取り、各行の値を関連データと比較する1つの方法です。これは、サブクエリが、メインクエリによって考慮される候補行ごとに異なる結果または結果のセットを返す必要がある場合に常に使用されます。つまり、相関サブクエリを使用して、親ステートメントによって処理される各行の値に応じて回答が決まるマルチパート質問に回答できます。
実際の例
これは、国ごとに最も視聴された映画を取得するSakilaサンプルデータベースに対するstackoverflowからのかなりうまいクエリです。
最初のステップは、各映画が各国で何回視聴されたかを数えることです。そのためのSELECTステートメントは次のとおりです:
SELECT F.title AS title, CO.country_id AS country_id, CO.country AS country_name, count(F.film_id) as times FROM customer C INNER JOIN address A ON C.address_id = A.address_id INNER JOIN city CI ON A.city_id = CI.city_id INNER JOIN country CO ON CI.country_id = CO.country_id INNER JOIN rental R ON C.customer_id = R.customer_id INNER JOIN inventory I ON R.inventory_id = I.inventory_id INNER JOIN film F ON I.film_id = F.film_id GROUP BY F.film_id, CO.country_id;
上記のクエリとNavicat Premium 16での結果は次のとおりです:
次のステップは、上記の結果を、最も視聴された映画のタイトルと視聴回数とともに、国のリストに変換することです。次に、相関サブクエリを使用した完全なクエリと、それに続いて説明を示します:
説明:
- サブクエリ:国別にグループ化された映画カウントのリストを取得します。
- GROUP_CONCAT(title ORDER BY times DESC SEPARATOR '|||')は、その「行」の全てのタイトルを返します。最も視聴されたタイトルが最初になります。区切り文字は、タイトルに含まれていない限り問題ありません。
- SUBSTRING_INDEX('...', '|||', 1)は、"|||"が見つかるまで文字列の最初の部分を抽出します。
相関サブクエリに関する最終的な考え
今日のブログでは、Navicat Premium 16を使用して相関サブクエリを作成する方法を学びました。相関サブクエリは遅くなる可能性があることにあらかじめ注意が必要です。ただし、適切な最適化を行うことで、速度を大幅に向上させることができます。