SQLの実行順序 — 書く順と実行する順は違う

SQLの句が実際に評価される順序(FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY)を解説します。なぜWHEREで列の別名が使えないのか、といった「つまずき」の理由が腑に落ちます。

SQL は SELECT から書き始めますが、実は書く順序と実行される順序は違います。この「実行順序」を知ると、「なぜ WHERE で別名が使えないのか」「なぜ GROUP BY より先に WHERE で絞るのか」といった、初学者がつまずきがちな疑問が一気に解決します。

論理的な実行順序

一般的な SELECT 文は、おおよそ次の順で評価されます(論理的な順序であり、実際の内部処理は最適化されます)。

何をするか
1FROM / JOINどのテーブルから、どう結合して読むか
2WHERE行を条件で絞り込む(集約の前)
3GROUP BY行をグループにまとめる
4HAVINGグループを条件で絞り込む(集約の後)
5SELECT出力する列を選ぶ・計算する
6ORDER BY並べ替える
7LIMIT件数を制限する

書くときは SELECT が先頭ですが、評価は FROM から始まり、SELECT はかなり後です。この順序を頭に入れておくと、多くの挙動が説明できます。

なぜ WHERE で別名が使えないのか

次のクエリはエラーになります。

query.sql
SELECT salary * 12 AS annual
FROM employees
WHERE annual > 6000;   -- エラー: annual は使えない

理由は実行順序です。WHERE(2 番目)が評価される時点では、SELECT(5 番目)で作った別名 annual はまだ存在しません。別名は SELECT で初めて作られるため、それより前の WHERE からは見えないのです。

正しくは、WHERE では式をそのまま書きます。

query.sql
SELECT salary * 12 AS annual
FROM employees
WHERE salary * 12 > 6000;

一方、ORDER BY(6 番目)は SELECT より後なので、別名を使えます。

query.sql
SELECT salary * 12 AS annual
FROM employees
ORDER BY annual DESC;   -- これは OK

なぜ WHERE と HAVING を使い分けるのか

WHERE(2 番目)は集約のHAVING(4 番目)は集約のに評価されます。だから、

  • 個々の行を絞るのは WHERE
  • 集計結果(AVGCOUNT など)で絞るのは HAVING

という使い分けになります。これも実行順序から自然に導けます。

query.sql
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 を書いて実行・自動採点できる演習問題に挑戦できます。
問題一覧へ →