SQLの実行順序 — 書く順と実行する順は違う
SQLの句が実際に評価される順序(FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY)を解説します。なぜWHEREで列の別名が使えないのか、といった「つまずき」の理由が腑に落ちます。
SQL は SELECT から書き始めますが、実は書く順序と実行される順序は違います。この「実行順序」を知ると、「なぜ WHERE で別名が使えないのか」「なぜ GROUP BY より先に WHERE で絞るのか」といった、初学者がつまずきがちな疑問が一気に解決します。
論理的な実行順序
一般的な SELECT 文は、おおよそ次の順で評価されます(論理的な順序であり、実際の内部処理は最適化されます)。
| 順 | 句 | 何をするか |
|---|---|---|
| 1 | FROM / JOIN | どのテーブルから、どう結合して読むか |
| 2 | WHERE | 行を条件で絞り込む(集約の前) |
| 3 | GROUP BY | 行をグループにまとめる |
| 4 | HAVING | グループを条件で絞り込む(集約の後) |
| 5 | SELECT | 出力する列を選ぶ・計算する |
| 6 | ORDER BY | 並べ替える |
| 7 | LIMIT | 件数を制限する |
書くときは SELECT が先頭ですが、評価は FROM から始まり、SELECT はかなり後です。この順序を頭に入れておくと、多くの挙動が説明できます。
なぜ WHERE で別名が使えないのか
次のクエリはエラーになります。
SELECT salary * 12 AS annual
FROM employees
WHERE annual > 6000; -- エラー: annual は使えない理由は実行順序です。WHERE(2 番目)が評価される時点では、SELECT(5 番目)で作った別名 annual はまだ存在しません。別名は SELECT で初めて作られるため、それより前の WHERE からは見えないのです。
正しくは、WHERE では式をそのまま書きます。
SELECT salary * 12 AS annual
FROM employees
WHERE salary * 12 > 6000;一方、ORDER BY(6 番目)は SELECT より後なので、別名を使えます。
SELECT salary * 12 AS annual
FROM employees
ORDER BY annual DESC; -- これは OKなぜ WHERE と HAVING を使い分けるのか
WHERE(2 番目)は集約の前、HAVING(4 番目)は集約の後に評価されます。だから、
- 個々の行を絞るのは
WHERE - 集計結果(
AVGやCOUNTなど)で絞るのはHAVING
という使い分けになります。これも実行順序から自然に導けます。
SELECT dept, AVG(salary) AS avg_salary
FROM employees
WHERE hire_year >= 2020 -- 先に行を絞る
GROUP BY dept
HAVING AVG(salary) >= 550; -- 集約後に絞る実行順序が効くその他の場面
- 集約関数を WHERE に書けない:
WHERE COUNT(*) > 1はエラー。集約はGROUP BY(3 番目)より後なので、WHERE(2 番目)では使えない →HAVINGを使う - DISTINCT は SELECT の一部:重複除去は
SELECTの段階なので、ORDER BYからは DISTINCT 後の結果が見える
まとめ
- SQL は書く順(SELECT が先頭)と実行順(FROM が最初)が違う
- 実行順は
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT WHEREで別名や集約関数が使えないのは、それらが後の段階で作られるからORDER BYは最後なので別名を使える
実行順序は、SQL の「なぜ?」の多くを説明してくれる地図のようなものです。エラーの理由が分からなくなったら、この順序に立ち返ってみてください。
手を動かして確認しましょうブラウザ上で SQL を書いて実行・自動採点できる演習問題に挑戦できます。
問題一覧へ →