WordPressのDBサーバー MySQLでSELECT文のSQLを実行していた時にふと気付きました。
MySQLでは、GROUP BY句・HAVING句でカラムに付けた別名(AS句)を指定できるんですね。
確かOracle・PostgreSQL・SQL Serverなどの他のRDMSは普通使えなかったような…。
ということで、調べました。
なお、今回のバージョンは以下の通りです。
- MySQL 5.7
SQL SELECT文の評価・実行順序
SQLのSELECT文を実行すると、RDMSの内部で各句が順番に解釈されますが、その際の順番を実行順序(評価順序)と言います。
その実行順序は上から順・下から順という単純なものではなく、次のようになっています。
- FROM
- WHERE(結合条件)
- START WITH
- CONNECT BY
- WHERE(行のフィルタ条件)
- GROUP BY
- HAVING
- MODEL
- SELECT
- UNION、MINUS、INTERSECTなどの集合演算
- ORDER BY
こちらはOracleのものですが、どのRDMSも基本的にこんな感じです。
赤字は主要なものです。
SELECT句はSQL文の先頭ですが、だいぶ後ろの方になっていますね。
そのため、SELECT句でAS句を使用してカラムに別名を付けたものをWHERE句などで使用することはできません。
WHERE句などの評価順序がSELECT句よりも前だからです。
逆に、ORDER BY句ならSELECT句よりも実行順序が後ろなので使用できます。
例えば、WordPressで2019年に公開した投稿・固定ページの件数を月ごとに出すSQLは、以下のようになります。
SELECT
DATE_FORMAT(post_date, '%Y%m') AS yyyymm
,post_type AS post_or_page
,COUNT(ID) AS cnt
FROM
posts
WHERE
(post_type = 'post'
OR post_type = 'page')
AND post_status = 'publish'
AND post_date BETWEEN '20190101' AND '20191231'
GROUP BY
DATE_FORMAT(post_date, '%Y%m')
,post_type
HAVING
COUNT(ID) > 1
ORDER BY
yyyymm
,post_or_page
SELECT句でAS句を使用してカラムにそれぞれ別名を付けていますが、通常これらはWHERE句・GROUP BY句・HAVING句ではその別名を使用できません。
ちなみに、このSQLはこんな感じでデータが取れます。
yyyymm | post_or_page | cnt |
---|---|---|
201901 | page | 2 |
201901 | post | 2 |
201902 | post | 15 |
201903 | post | 17 |
201904 | post | 10 |
201905 | post | 7 |
201906 | post | 2 |
201907 | post | 6 |
201908 | post | 6 |
201909 | post | 10 |
201910 | post | 7 |
201911 | post | 11 |
201912 | post | 8 |
MySQLはGROUP BY句・HAVING句にカラムの別名を使用可
MySQLの場合は、SELECT句で指定した別名をGROUP BY句・HAVING句で使用できます。
先ほどのSQLを以下のように変更しても、エラーなく実行できます。
SELECT
DATE_FORMAT(post_date, '%Y%m') AS yyyymm
,post_type AS post_or_page
,COUNT(ID) AS cnt
FROM
posts
WHERE
(post_type = 'post'
OR post_type = 'page')
AND post_status = 'publish'
AND post_date BETWEEN '20190101' AND '20191231'
GROUP BY
yyyymm
,post_or_page
HAVING
cnt > 1
ORDER BY
yyyymm
,post_or_page
これは知らなかった。。
特に、COUNTなどのグループ関数を使用している場合は見やすいし、理解しやすいのでありがたいです。
MySQLの公式ドキュメント内を探してみたんですが、実行順序についての記載を見つけることはできませんでした。
なので、MySQLはGROUP BY句・HAVING句で別名使用可と覚えておこうと思います。
最後に
今回は、SQL SELECT文の評価順序(実行順序)についてでした。
MySQLだけは特殊で、GROUP BY句・HAVING句にSELECT句で指定したカラムの別名を使用できます。
コメント