「サブクエリ=とりあえず (SELECT …)
を書くもの」と雑に覚えていました。
しかし、書く場所ごとの役割から考えると理解が深まったのでまとめます。
1. SELECT 句に書くサブクエリ ──「列を増やす」ための道具箱
非相関サブクエリ: 1 回だけ実行して全行に同じ値を貼る
SELECT
name,
(SELECT AVG(salary) FROM employees) AS avg_salary
FROM employees;
-
動き:
SELECT AVG(salary)
が一度だけ走り、戻り値 1 つを全行に付与 - 用途: 全体平均・最大値・設定情報など 「全員同じ列値でいい」 ケース
相関サブクエリ: 行ごとに実行して“行に合わせた値”を算出
SELECT
e1.name,
(SELECT AVG(e2.salary)
FROM employees e2
WHERE e2.department_id = e1.department_id) AS dept_avg_salary
FROM employees e1;
-
動き: 外側行の
department_id
ごとに内側が再実行 → 行ごとに異なる値 - メリット: 部署ごとの平均、顧客ごとの最新注文金額など “行ごとに違う計算” が楽
- デメリット: 実行回数 = 行数 になるので大規模データだと遅い。JOIN への書き換え検討を。
ここで覚えるポイント
❶ 非相関 = “一気に 1 回” → 全行同じ
❷ 相関 = “行ごとに再実行” → 行ごとに違う値
SELECT 句の目的は「列を増やす」こと。その列が“全員同じ”か“行ごとに違う”かで相関を選ぶ。
2. FROM 句に書くサブクエリ ──「一時テーブル化」してクエリを分ける
非相関サブクエリだけ(相関は不可)
SELECT sub.department_id, AVG(sub.salary)
FROM (
SELECT department_id, salary FROM employees
) AS sub
GROUP BY sub.department_id;
-
動き:
SELECT department_id, salary …
が 1 度走り、結果セットを “仮テーブルsub
” にする - 用途: 複雑な計算を切り出して読みやすくする、インラインビュー代わりに使う
- 相関が不可な理由: FROM 句のサブクエリは “先に独立して完結” してから外側へ渡る設計だから。
覚えるポイント
FROM 句サブクエリ = “作業用ビュー”。
外側行を参照できない=相関不可。逆に言えば「外側に依存しないまとまりを切り出す」のに最適。
3. WHERE 句に書くサブクエリ ──「条件を動的に作る」フィルター職人
非相関サブクエリ: 一度だけ実行してしきい値を決める
SELECT name
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);
- 動き: 平均給与を 1 回計算 → その値を境にフィルタ
- 用途: “全体平均より高い人” “最大売上の製品” など 比較対象が 1 値で済む 場面
相関サブクエリ: 行ごとに条件が変わるフィルター
SELECT e1.name
FROM employees e1
WHERE salary > (
SELECT AVG(e2.salary)
FROM employees e2
WHERE e2.department_id = e1.department_id
);
-
動き: 外側行の
department_id
ごとに平均を再計算 → 行ごと評価 - 用途: “部署平均より高い人” “顧客ごと累計より多い注文” など 行依存の条件
- 注意: 実行回数 = 行数。パフォーマンス課題がある場合は JOIN + GROUP BY への変換を検討。
覚えるポイント
WHERE 句サブクエリは「**値を返すより“真偽判定に使う”**イメージで書く」とブレにくい。
4. HAVING 句に書くサブクエリ ──「集計結果に“外基準”をぶつける」
非相関サブクエリで全体基準を一発参照
SELECT department_id, AVG(salary)
FROM employees
GROUP BY department_id
HAVING AVG(salary) > (SELECT AVG(salary) FROM employees);
- 動き: 全体平均を 1 回計算 → 部署ごとの平均と比較
- 使いどころ: レポート系で 「各グループ vs 全体」 を比べたい場面が定番
- 相関はほぼ使わない: 相関的に複雑になるなら、CTE/サブクエリをFROM句に切り出す設計を
覚えるポイント
HAVING 句サブクエリは「集計後のロジック」で使う。
外側のGROUP BY結果と比べる“外部基準値”を作るのが主目的。
まとめ ──「どこに書くか」でサブクエリは別物になる
書く場所 | 典型目的 | 非相関の動き | 相関/動き | 代表的な落とし穴 |
---|---|---|---|---|
SELECT | 列を追加 | 1回のみ実行 | ◯ /行ごと再実行 | 行数多いと遅い |
FROM | 一時表化 | 1回のみ実行 | × /不可 | 読み手がネストに迷う |
WHERE | 条件値 | 1回のみ実行 | ◯ /行ごと再実行 | 相関で遅くなる |
HAVING | 集計比較 | 1回のみ実行 | △ /実用少ない | 論理が絡まりやすい |