やるしかなっちゃん

やるしかない!

行持ち⇔列持ち

最近はもう何もしたくないので本を読みまくってる。
そんな流れで達人に学ぶDB設計を読んだ。

達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ

達人に学ぶDB設計 徹底指南書 初級者で終わりたくないあなたへ

自分はこの本をレビューできるほどDB力がないので感想としては素晴らしい本だったの一言しか思い浮かばない。
まぁそんなことはどうでもいいとして、行持ちと列持ちの変換が心に響いたので以下メモ。

こんなデータがあるとする 。

ID NAME OPTION
001 aaa x
y
002 bbb
003 ccc x
y
z

この時、列持ちテーブルは次のようになる。

ID NAME OPTION1 OPTION2 OPTION3
001 aaa x y NULL
002 bbb NULL NULL NULL
003 ccc x y z

このテーブルに対して次のSQL文を実行すると行持ちテーブルに変換できる。

SELECT ID, 1 AS OPTION_ID, NAME,  OPTION1
FROM TABLE_NAME
WHERE OPTION1 IS NOT NULL
UNION
SELECT ID, 2 AS OPTION_ID, NAME,  OPTION2
FROM TABLE_NAME
WHERE OPTION2 IS NOT NULL
UNION
SELECT ID, 3 AS OPTION_ID, NAME,  OPTION3
FROM TABLE_NAME
WHERE OPTION3 IS NOT NULL

このSQL文によってできる行持ちテーブルは次の様になる。

ID OPTION_ID NAME OPTION
001 1 aaa x
001 2 aaa y
003 1 ccc x
003 2 ccc y
003 3 ccc z

この行持ちテーブルを列持ちテーブルに変換するSQL文はこんな感じ。

SELECT ID,
       MAX(NAME) AS NAME,
       MAX(CASE WHEN OPTION_ID = 1 THEN OPTION ELSE NULL END) AS OPTION1,
       MAX(CASE WHEN OPTION_ID = 2 THEN OPTION ELSE NULL END) AS OPTION2,
       MAX(CASE WHEN OPTION_ID = 3 THEN OPTION ELSE NULL END) AS OPTION3
FROM TABLE_NAME
GROUP BY ID

IDでグループ化しているので無理やり集計関数を使わないといけない当たりがちょっと気持ち悪いけどでもまあしょうがない。
列持ち、縦持ちどっちにも利点と欠点があるけど基本的には列持ちはグレーノウハウだよってこの本では書かれている。
でもパフォーマンス面の話があんまり書いてなかったので調べたらこんな感じだった。
横持ちと縦持ち
確かにこれはグレーだ^^;