WINDOW関数の話はひと段落しましたが、今回もPrestoの話です。例によって僕はトレジャーデータで検証しています。(今回の記事で紹介する内容はMySQLでは動かないという話も見かけました。)
ここ最近の記事で掲載したサンプルのSQLでは、テーブルに保存されたデータではなくSQLで生成したデータを使っていました。事前にこういうデータを用意してますとか書くのが面倒だったので。その際、ARRAY関数で作った配列を並べて、UNNESTでテーブル型に変換していたのですが、実はVALUES関数をつかってダミーデータを作ることもできるそうです。
この機会に、VALUES関数について調べたので、わかったことを記事にまとめておきます。PrestoのVALUES関数のドキュメントはこちらです。
参考: VALUES — Presto 0.261 Documentation
Description を読むと、VALUESは問い合わせ(query)が使用できる場所ならどこでも使用できる、トップレベルでさえ使える、といきなり衝撃的なことが書かれています。僕は、INSERT文などの特定の構文の中でしか使えないと思っていました。
試しにトップレベルで使ってみましょう。
VALUES 1, 2, 3
-- 出力結果
_col0
1
2
3
確かに、無名列(_col0)に3行のレコードが生成されました。
複数列のデータを作ることもできます。
VALUES
(1, 'a'),
(2, 'b'),
(3, 'c')
-- 出力結果
_col0, _col1
1, 'a'
2, 'b'
3, 'c'
ドキュメントには、ASを使えばテーブルと列に名前も付けれる、と書かれているので、色々試したのですが、トップレベルでVALUES を使った場合にASで列名をつける方法は結局見つけられませんでした。いろんな位置にカッコをつけたりして検証したのですが。
無名テーブルではなく、テーブル名と列名をつけたい場合は、次のようにSELECT文のFROM句の中で使うことで実現できます。
SELECT
id,
name
FROM
(
VALUES
(1, 'a'),
(2, 'b'),
(3, 'c')
) AS t(id, name)
-- 出力結果
id, name
1, 'a'
2, 'b'
3, 'c'
この結果は、UNNESTを使って書いた下のクエリの結果と同じになります。
SELECT
id,
name
FROM
UNNEST(
ARRAY[1, 2, 3],
ARRAY['a', 'b', 'c']
) AS t(id, name)
UNNEST と VALUES のどちらがいいか、という話ですが 読みやすさというか、直感的でぱっと見で結果の予想がつきやすいのは VALUESの方なんじゃないかなと思います。ただ、10行くらいのダミーデータを生成しようとすると、UNNESTの方が行数が少なくなりやすく、このブログのサンプルコードとしてはそちらの方が使いやすかったりします。非本質的な部分なのであまりスペースを取りたくないので。
処理速度等の性能面の比較は行っていません。性能が気になるほどの莫大なデータをこのような方法でSQLに直接書くべきではないと思いますので、もしそのような大規模データをサンプルとして用意したい場合は、VALUESを使うとか言ってないで、素直にどの下のテーブルに格納してそこからSELECTした方が良いと思います。