MySQL にはクエリ中にのみ有効なテーブルを作る機能があります。テーブルを作る際によくある書き方として次があります。
SELECT 1 as line, '浜松太郎' as name, 'hamamatsu@example.com' as email; -- line,name,email -- 1,浜松太郎,hamamatsu@example.com
SELECT 中に直に値を埋め込み as で列としての名前を与えます。これで出来上がったテーブルは JOIN やサブクエリなどで普通のテーブルと同様に扱えます。
SELECT 中に直に埋め込む都合上、この方法では一行しか表せません。そのためこの方法の延長線上で複数行を表現するとなると次の様にする必要があります。
SELECT 1 as line, '浜松太郎' as name, 'hamamatsu@example.com' as email UNION ALL SELECT 2, '静岡太郎', 'shizuoka@example.com' UNION ALL SELECT 3, '愛知太郎', 'aichi@example.com' UNION ALL SELECT 4, '山梨太郎', 'yamanashi@example.com' ; -- line,name,email -- 1,浜松太郎,hamamatsu@example.com -- 2,静岡太郎,shizuoka@example.com -- 3,愛知太郎,aichi@example.com -- 4,山梨太郎,yamanashi@example.com
SELECT と UNION が連続するのが冗長な感じがします。この SQL 文地味に辛いのが EXPLAIN で SQL 文について読み取るときです。上記を EXPLAIN にかけると次の様な結果が出ます。
MySQL :: MySQL 8.0 リファレンスマニュアル :: 13.8.2 EXPLAIN ステートメント
id,select_type,table,partitions,type,possible_keys,key,key_len,ref,rows,filtered,Extra 1,PRIMARY,,,,,,,,,,No tables used 2,UNION,,,,,,,,,,No tables used 3,UNION,,,,,,,,,,No tables used 4,UNION,,,,,,,,,,No tables used
UNIONする度にノイズ的な説明レコードが増えます。
SELECT と UNION で複数のレコードを持つテーブルを作る方法とその問題点を紹介しました。これを改善するテーブルの作り方として次があります。
SELECT * FROM ( VALUES ROW( 1, '浜松太郎', 'hamamatsu@example.com'), ROW( 2, '静岡太郎', 'shizuoka@example.com'), ROW( 3, '愛知太郎', 'aichi@example.com'), ROW( 4, '山梨太郎', 'yamanashi@example.com') ) users(line, name, email); -- line,name,email -- 1,浜松太郎,hamamatsu@example.com -- 2,静岡太郎,shizuoka@example.com -- 3,愛知太郎,aichi@example.com -- 4,山梨太郎,yamanashi@example.com
MySQL の VALUES はテーブルはテーブルのコンストラクタとも使えるため上記の様にして、複数行を持つテーブルをその場で作れます。
MySQL :: MySQL 8.0 リファレンスマニュアル :: 13.2.14 VALUES ステートメント
また、こちらは式であるために EXPLAIN の結果が増えません。結果は次です。
id,select_type,table,partitions,type,possible_keys,key,key_len,ref,rows,filtered,Extra 1,PRIMARY,,,ALL,,,,,4,100, 2,DERIVED,,,,,,,,,,No tables used
上記の様に VALUES を使うと比較的わかりやすく短い SQL 文で複数行を持つテーブルを作れます。MySQL の持つ計算機能を用いて複数の値の組み合わせについてなんやかんやしたい時にこの方法を覚えておくと役に立つ時があります。