BAD DB設計に対するSQLパターン応用編1 カンマ区切りのカラムを列(縦方向に分解)

今回は、BAD DB設計に対するSQLパターン入門編の応用編です。

1カラムの中にカンマ区切りでデータが入っているBAD DB設計、これもわりと良く見るパターンですね。これを列に分解したい場合がある。簡単そうで実はわりと難しいテーマです。残念ながら、ぐぐっても解決方法は出てこない。

↑これはいい線いってましたね。

SELECT '1,3,5,7,8'csv
1,3,5,7,8

これを列に変換

SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(csv,',',v.n),',',-1) 
 FROM (SELECT '1,3,5,7,8'csv) c,
      (SELECT 1 n UNION ALL 
       SELECT 2   UNION ALL
       SELECT 3   UNION ALL
       SELECT 4   UNION ALL
       SELECT 5) v 
WHERE  LENGTH(csv)-LENGTH(REPLACE(csv,',',''))+1 >=v.n
1
3
5
7
8

『単純結合』と『仮想表』を使うところは入門編とおなじで、これに加えてSUBSTRING_INDEXを2つ使って、カンマ区切りのカラムから指定位置のデータを取り出している。ちなみにFIND_IN_SETでは、カンマ区切りデータ中で一致するデータの位置を得る関数なので、似ているが使えない。

WHERE  LENGTH(csv)-LENGTH(REPLACE(csv,',',''))+1 >=v.n

WHERE句では、LENGTH関数とREPLACE関数を使用することで、カンマの数を取得している。

仮想表はカンマの数の最大数分だけ必要なので注意すること。
単純結合を使用するので、カンマの数が増えるほど、仮想表の列が大きくなり、その乗数分だけ処理が重くなる。