SQLアンチパターンのジェイウォークを縦持ちテーブルに変換する

概要

SQLアンチパターンの1つであるジェイウォークと遭遇して、
一回のSQLで縦持ちのテーブルに変換できたのでその方法のメモです。

前提条件

テーブル

元テーブル

下記のようなテーブルがあります。

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関数を組み合わせると良い感じにジェイウォークを解消できますね。