MySQLはSELECT句とGROUP BY/HAVING句間の共通部分式を排除する?sleep()関数による検証方法
MySQLはSELECT句とGROUP BY句の共通部分式を排除するのか?
MySQLがSELECT句とGROUP BY句(またはHAVING句)に記述された同じ式を重複して評価していないか、つまり共通部分式の排除が行われているかを確認したい場合には、sleep()関数を使うのが手軽で確実な方法です。sleep()は指定した秒数だけ処理を一時停止する関数のため、式が何回評価されたのかを実行時間から読み取ることができます。なお、sleep()の戻り値は0なので、表示される値自体は変わりませんが、評価のたびに遅延が発生する点がポイントです。
検証に使用する構文
ケース1:SELECT句とGROUP BY句に同じ式をそのまま記述します。
SELECT yourColumnName + sleep(yourIntegerValue) FROM yourTableName GROUP BY yourColumnName + sleep(yourIntegerValue);
ケース2:SELECT句でエイリアスを定義し、GROUP BY句ではそのエイリアスを参照します。
SELECT yourColumnName + sleep(yourIntegerValue) AS anyAliasName FROM yourTableName GROUP BY anyAliasName;
検証用テーブルの作成
まず、動作確認用のテーブルを作成します。
mysql> create table sleepDemo
-> (
-> value int
-> );
Query OK, 0 rows affected (1.25 sec)
続いて、INSERTコマンドでテストデータを3件登録します。
mysql> insert into sleepDemo values(40); Query OK, 1 row affected (0.18 sec) mysql> insert into sleepDemo values(60); Query OK, 1 row affected (0.19 sec) mysql> insert into sleepDemo values(60); Query OK, 1 row affected (0.10 sec)
SELECT文ですべてのレコードを表示して確認しましょう。
mysql> select *from sleepDemo;
実行結果は次の通りです。
+-------+ | value | +-------+ | 40 | | 60 | | 60 | +-------+ 3 rows in set (0.00 sec)
ケース1:同じ式を直接記述した場合
SELECT句とGROUP BY句の両方に「value + sleep(3)」という同一の式を記述して実行します。
mysql> SELECT value+sleep(3)
-> FROM sleepDemo
-> GROUP BY value+sleep(3);
実行結果は以下の通りです。
+----------------+ | value+sleep(3) | +----------------+ | 40 | | 60 | +----------------+ 2 rows in set (9.00 sec)
実行時間は9.00秒でした。内訳を見ると、40の行で3秒、60の行で3秒、もう一つの60の行で3秒と、3行それぞれに対してsleep(3)が1回だけ評価されています。もし共通部分式が排除されていなければ、GROUP BY句とSELECT句の両方で評価が行われ、実行時間はこれより大幅に長くなるはずです。
ケース2:エイリアスを使用した場合
次に、SELECT句でエイリアス「v」を定義し、GROUP BY句から参照する形式で実行します。
mysql> SELECT value+sleep(3) As v
-> FROM sleepDemo
-> GROUP BY v;
実行結果は以下の通りです。
+------+ | v | +------+ | 40 | | 60 | +------+ 2 rows in set (9.00 sec)
検証結果のまとめ
どちらのケースでも実行時間は9秒で、式は行ごとに1回しか評価されませんでした。この結果から、MySQLはSELECT句とGROUP BY句(HAVING句についても同様)の間で共通する部分式を排除し、評価結果を再利用していることが確認できます。エイリアスを使った書き方でも挙動は変わらないため、実務では可読性の高いエイリアス形式を活用するのがおすすめです。
-
MySQLで0を末尾に回して並べ替える!条件付きSELECTとORDER BYの使い方
MySQLでは、ORDER BY句に「カラム名=0」という条件式を組み合わせることで、0以外の値を昇順に並べたうえで、0のレコードだけを末尾にまとめて表示できます。この記事では、その具体的な書き方と実行例を分かりやすく解説します。基本構文select * from yourTableName order by yourColumnName=0, yourColumnName;この構文のポイントは、yourColumnName=0 がブール値として評価される点です。値が0であれば「1(真)」、0以外であれば「0(偽)」となるため、昇順ソートでは0以外の値の行が先に並び、その後ろに0の行が配置され
-
【MySQL】単一クエリでUNION SELECTとIN句を組み合わせる方法
はじめにMySQLでは、UNION SELECTとIN句を単一のクエリ内で組み合わせることができます。これにより、複数のテーブルのデータを統合した上で、特定の条件に一致するレコードだけを効率的に抽出できます。本記事では、2つのテーブルを作成し、サブクエリとUNIONを活用して目的のデータを取得する手順を具体例とともに解説します。最初のテーブルを作成するまず、以下のコマンドでテーブル「DemoTable1」を作成します。mysql> create table DemoTable1 -> ( -> StudentId int, -> StudentN