SQLアンチパターンのジェイウォークを縦持ちテーブルに変換する
概要
SQLアンチパターンの1つであるジェイウォークと遭遇して、
一回のSQLで縦持ちのテーブルに変換できたのでその方法のメモです。
前提条件
- PostgreSQL 11.1
テーブル
元テーブル
下記のようなテーブルがあります。
id | value |
---|---|
1 | apple,orange,banana |
2 | apple |
3 | orange,banana |
valueにはカンマ区切りで値が入っています。
テーブル名は「jaywalk_table」とします。
取得したい形
id | branch_number | splited_value |
---|---|---|
1 | 1 | apple |
1 | 2 | orange |
1 | 3 | banana |
2 | 1 | apple |
3 | 1 | orange |
3 | 2 | banana |
カンマ区切りの値に対してそれぞれを1レコードとして枝番号をつけます。
SQL
実行したSQLは下記です。
SELECT id, ROW_NUMBER() OVER(PARTITION BY id) AS branch_number, splited_value FROM ( SELECT id, regexp_split_to_table(value,',') AS splited_value FROM jaywalk_table ) AS temp
解説
regexp_split_to_table
regexp_split_to_table関数は指定した区切り文字で区切って、区切られた値をそれぞれレコードに変換します。
例えば、下記のSQLを実行すると・・・
SELECT regexp_split_to_table('apple,orange,banana', ',')
下記のような結果が返ってきます。
regexp_split_to_table |
---|
apple |
orange |
banana |
この関数を使えばジェイウォークは解消されます。
ROW_NUMBER
ROW_NUMBER関数はWindow関数の一つです。
Window関数はグループごとに計算を行い、計算された結果を各レコードに返します。
今回でいくとOVER(PARTITION BY id)
はid
ごとにグルーピングすることを表し、
ROW_NUMBER()
でそのグルーピング内で行数を返してねという感じの流れです。
まとめ
集合を返す関数とWindow関数を組み合わせると良い感じにジェイウォークを解消できますね。