テーブルの横持ちと縦持ちについて解説します。
横持ち、縦持ちとは
以下のように、属性を横に並べたテーブルのことを横持ちと言います(氏名、年齢、性別などが属性の例です)。
行番号 | 属性1 | 属性2 | 属性3 |
1 | $a$ | $b$ | $c$ |
2 | $d$ | $e$ | $f$ |
一方、1行に1つの情報のみを格納した、以下のようなテーブルのことを縦持ちと言います。
行番号 | 属性 | 値 |
1 | 属性1 | $a$ |
1 | 属性2 | $b$ |
1 | 属性3 | $c$ |
2 | 属性1 | $d$ |
2 | 属性2 | $e$ |
2 | 属性3 | $f$ |
使い分け
・人が見るときには、横持ちの方が整っていて見やすいです。実際、多くの人が「横持ちの方が普通、縦持ちはあまり見ないし分かりにくい」という感覚を持っているのではないでしょうか。
・縦持ちの方が、属性の追加や削除に柔軟に対応できます。例えば、上記の例で属性4を追加して、と言われたときに、横持ちの場合はテーブル定義を変更する必要がありますが、縦持ちの場合は、テーブル定義はそのまま(行番号、属性、値、という定義のまま)です。行が増えるだけです。
・また、テーブルがスパースの場合(多くのマスに情報が入っていなく、NULLの場合)は、縦持ちの方が行数が少なくなり、コンパクトになります。例えば、上記の例で、$a$ と $e$ 以外が NULL の場合、縦持ちは
行番号 | 属性 | 値 |
1 | 属性1 | $a$ |
2 | 属性2 | $e$ |
とコンパクトになります。
横持ちを縦持ちに直す
ここから先はSQL で縦横変換まとめ(pivot と unpivot)を参考にしました。
SELECT 行番号, ‘属性1’ AS 属性, 属性1 AS 値 FROM 横持ちのテーブル名
UNION ALL
SELECT 行番号, ‘属性2’ AS 属性, 属性2 AS 値 FROM 横持ちのテーブル名
UNION ALL
SELECT 行番号, ‘属性3’ AS 属性, 属性3 AS 値 FROM 横持ちのテーブル名
[説明]
まず、属性1の部分のみを抽出、属性2の部分のみを抽出、属性3の部分のみを抽出したテーブルをそれぞれ作成し、最後に縦に全てくっつけるというイメージです。
縦持ちを横持ちに直す
SELECT 行番号,
max(CASE WHEN 属性 = ‘属性1’ THEN 値 END) AS 属性1,
max(CASE WHEN 属性 = ‘属性2’ THEN 値 END) AS 属性2,
max(CASE WHEN 属性 = ‘属性3’ THEN 値 END) AS 属性3
FROM 縦持ちのテーブル名
GROUP BY 行番号
[説明]
行番号で集約した上で、属性を1つずつSELECTしていくというイメージです。(集計の対称は1つの値なので)集計関数は max でなくても、avg や sum でもOKです(同じ結果になります)。
次回は JOINによるテーブルの結合方法5種類を整理 を解説します。