研修でSQLを学ぶと思いますが。SQLの解析順って教えてもらうのだろうか。
SQLの解析順を知っているとSQLが文法エラーになったときの助けになる時があるよ。っていう話です。
今回はSELECT文の解析順序の話です。
検証ではPostgreSQLを使用しています。
さっそくですが、
このSQLは実行できます。
SELECT
price * 1.1 AS price_with_tax
FROM sp_work.aoki_products
ORDER BY price_with_tax;
しかし、こちらのSQLはエラーになります。
SELECT
price * 1.1 AS price_with_tax
FROM sp_work.aoki_products
WHERE price_with_tax = 110;
=> SQLエラー [42703]: ERROR: column "price_with_tax" does not exist
どちらもSELECT句で指定しているprice_with_tax(AS別名)を使ってます。
ORDER BY句では使用可能ですが、WHERE句ではdoes not existになってしまいます。
なぜWHERE句ではdoes not existになるの??
SQLの解析順序を知っていれば、理由がわかかります。
こちらが、SQL解析順序です。
- FROM句
- JOIN句
- WHERE句
- GROUP BY句
- HAVING句
- SELECT句
- ORDER BY句
- DISTINCT句
- LIMIT OFFSET句
WHERE句の解析はSELECT句の前で行われる為、WHERE句ではまだprice_with_taxを認識できません。
なので、does not existエラーになるわけです。
このような集計関数を使用したSQLも初心者がやりがちなミスです。
SELECT
category,
max(price)
FROM sp_work.aoki_products
WHERE max(price) > 100
GROUP BY category
=> SQLエラー [42803]: ERROR: aggregate functions are not allowed in WHERE
グルーピングして集計する場合、GROUP BY句でグループ指定をします。このGROUP BY句よりも先にWHERE句が解析されるので、WHERE句では集計関数は使えません。
では、GROUP BYが無ければよいのか??
SELECT
max(price)
FROM sp_work.aoki_products
WHERE max(price) > 100
=> SQLエラー [42803]: ERROR: aggregate functions are not allowed in WHERE
だめです。
GROUP BYが無い場合は、全件でグルーピングしていると思って下さい。
グルーピングしているのがWHERE句解析後のGROUP BY句解析タイミングなのでエラーになります。
つまり、WHERE句では、集計関数は使えません。
集計関数を検索条件にしたい場合は、HAVING句を使いましょう。
SELECT
category,
max(price)
FROM sp_work.aoki_products
GROUP BY category
HAVING max(price) > 100
さいごに
数年後にはSQLもAIが書いてくれるんだろうなー