前回の記事で紹介したPrestoのMap型ですが、これを使うとデータの縦横変換(ピボット)がスマートに行えます。
参考: ピボットテーブル&チャート
上記リンク先のトレジャーデータの記事中の画像のテーブルを例に説明します。
uid | key | value |
---|---|---|
101 | c1 | 11 |
101 | c2 | 12 |
101 | c3 | 13 |
102 | c1 | 21 |
102 | c2 | 22 |
102 | c3 | 23 |
このようなテーブルを次のように変換したいとします。
uid | c1 | c2 | c3 |
---|---|---|---|
101 | 11 | 12 | 13 |
102 | 21 | 22 | 23 |
この変換は、MAP_AGGを使って、key列とvalue列の対応のMapを一旦作成し、
それぞれのMapから各Keyの値を取り出すことで実現できます。
具体的にクエリにしたのが次です。
SELECT
uid,
kv['c1'] AS c1,
kv['c2'] AS c2,
kv['c3'] AS c3
FROM (
SELECT
uid,
MAP_AGG(key, value) AS kv
FROM
vtable
GROUP BY
uid
) AS t
個人的には服問い合わせはあまり好きではなく、PrestoではWITHを使って書きたいので次のようにすることが多いです。
WITH
t AS (
SELECT
uid,
MAP_AGG(key, value) AS kv
FROM
vtable
GROUP BY
uid
)
SELECT
uid,
kv['c1'] AS c1,
kv['c2'] AS c2,
kv['c3'] AS c3
FROM
t
Prestoではない、(MAP型のない)通常のSQLでは次のように書かないといけないのですが、
上記のMap型を使ったものの方が随分すっきりかけているように見えます。
(MAP_AGGを知らない人には読めないのが難点ですが)
SELECT
uid,
MAX(
CASE WHEN key = 'c1' THEN
value
ELSE
NULL
END
) AS c1,
MAX(
CASE WHEN key = 'c2' THEN
value
ELSE
NULL
END
) AS c2,
MAX(
CASE WHEN key = 'c3' THEN
value
ELSE
NULL
END
) AS c3
FROM
vtable
GROUP BY
uid