いわゆるマルチカラムアトリビュートのテーブルから、正規化されたテーブルに変換したいことはままあると思います。
id | a1 | a2 | a3 | a4 | a5… | b1 | b2 | b3 | b4 | b5… |
---|
のようなテーブルです。
そういうとき、unnest
を使うと便利っぽいです。
SELECT
id,
unnest(array[a1, a2, a3, a4, a5, ...]),
unnest(array[b1, b2, b3, b4, b5, ...])
FROM hoge;
のようにすると、縦横変換された形で値を取得することができます。
unnest
配列関数と演算子 に書かれているように、unnest
は配列を行集合に展開してくれる関数です。
これだけでは複数unnest
が使用された場合にどう展開されるのか不明なので実験してみました。
同じ長さの配列2つ
SELECT unnest(array[1, 2, 3]), unnest(array['hoge', 'fuga', 'piyo']);
1 hoge
2 fuga
3 piyo
スカラ値と同じ長さの配列2つ
SELECT 997, 998, 999, unnest(array[1, 2, 3]), unnest(array['hoge', 'fuga', 'piyo']);
997 998 999 1 hoge
997 998 999 2 fuga
997 998 999 3 piyo
違う長さの配列2つ
SELECT unnest(array[1, 2, 3]), unnest(array['hoge', 'fuga']);
1 hoge
2 fuga
3 hoge
1 fuga
2 hoge
3 fuga
スカラ値と違う長さの配列2つ
SELECT 997, 998, 999, unnest(array[1, 2, 3]), unnest(array['hoge', 'fuga']);
997 998 999 1 hoge
997 998 999 2 fuga
997 998 999 3 hoge
997 998 999 1 fuga
997 998 999 2 hoge
997 998 999 3 fuga
SELECT 997, 998, 999, unnest(array[1, 2, 3, 4]), unnest(array['hoge', 'fuga']);
997 998 999 1 hoge
997 998 999 2 fuga
997 998 999 3 hoge
997 998 999 4 fuga
考察
動作を見る限り、下記のことが言えそうです。
- スカラ値は
unnest
の動作に関与せず、展開後のすべての行に同じ値がつく。 -
unnest
が複数使われた場合には、各配列長の最小公倍数の行数が作成される。各行には、各配列の要素が順番に入る。
なので、配列長に気を使えば十分この用途に使うことができそうです。