SQL JOIN vs サブクエリ -- それぞれの使い分け
SQL JOINとサブクエリをパフォーマンス、可読性、柔軟性で比較します。それぞれのアプローチが適切な場合と、最新のオプティマイザの処理方法を学びます。
Practical Examples
詳細な説明
JOIN vs サブクエリ
JOINとサブクエリはどちらも複数のテーブルから関連データを取得できますが、動作が異なり、トレードオフも異なります。
同じクエリを2つの方法で
JOINを使用:
SELECT o.id, o.total, c.name
FROM orders AS o
INNER JOIN customers AS c ON o.customer_id = c.id
WHERE c.country = 'US';
サブクエリを使用:
SELECT o.id, o.total
FROM orders AS o
WHERE o.customer_id IN (
SELECT id FROM customers WHERE country = 'US'
);
JOINが優れている場合
- SELECT句で両方のテーブルのカラムが必要な場合。
- 関連テーブルの複数のカラムが必要な場合。
- 関連にまたがる集計データ(例:顧客ごとの注文商品のSUM)。
- オプティマイザが大きなデータセットに対してハッシュ結合やマージ結合を使用できる。
サブクエリが優れている場合
- 存在チェック:
WHERE EXISTS (SELECT 1 FROM ...)はより明確で、早期に短絡できる。 - サブクエリの結果が小さい:小さな結果セットの
IN (SELECT ...)は非常に読みやすい。 - 結合にきれいにマッピングできない行ごとの計算のための相関サブクエリ。
- 結合前の事前集計のための
FROM句の派生テーブル。
パフォーマンスの実際
最新のクエリオプティマイザ(PostgreSQL 10+、MySQL 8+、SQL Server 2016+)はINサブクエリを自動的にセミジョインに変換し、明示的なJOINと同じ実行プランを生成することがよくあります。ただし、行ごとに1回実行される相関サブクエリは、JOINよりも大幅に遅くなる可能性があります。
可読性の経験則
サブクエリが意図をより明確にする場合(「米国の顧客の注文を取得」)、サブクエリを使用します。両方のテーブルからデータを取得する必要がある場合、JOINを使用します。迷った場合は、両方でEXPLAINを実行して比較してください。
中間的なアプローチとしてのCTE
共通テーブル式(WITH句)を使用すると、複雑なロジックを名前付きの読みやすいステップに分割できます。サブクエリの明確さとJOINの柔軟性を兼ね備えています。
ユースケース
結果に複数のテーブルのカラムが必要な場合はJOINを、存在チェックや事前集計が必要な場合はサブクエリを選択します。パフォーマンスが重要なクエリではEXPLAIN ANALYZEを参考にしてください。