テーブルの横持ちと縦持ちの使い分けと変換

最終更新日 2018/12/28

テーブルの横持ちと縦持ちについて解説します。

横持ち、縦持ちとは

同じ情報でも、テーブルで表現する方法は1つではありません。

以下のように、属性を横に並べたテーブルのことを横持ちと言います(氏名、年齢、性別などが属性の例です)。

行番号 属性1 属性2 属性3
$a$ $b$ $c$
$d$ $e$ $f$

一方、1行に1つの情報のみを格納した、以下のようなテーブルのことを縦持ちと言います。

行番号 属性
属性1 $a$
属性2 $b$
属性3 $c$
属性1 $d$
属性2 $e$
属性3 $f$

使い分け

まずは横持ちのメリットを考えてみます。

・人が見るときには、横持ちの方が整っていて見やすいです。実際、多くの人が「横持ちの方が普通、縦持ちはあまり見ないし分かりにくい」という感覚を持っているのではないでしょうか。

一方、縦持ちにもメリットがあります。

・縦持ちの方が、属性の追加や削除に柔軟に対応できます。例えば、上記の例で属性4を追加して、と言われたときに、横持ちの場合はテーブル定義を変更する必要がありますが、縦持ちの場合は、テーブル定義はそのまま(行番号、属性、値、という定義のまま)です。行が増えるだけです。

・また、テーブルがスパースの場合(多くのマスに情報が入っていなく、NULLの場合)は、縦持ちの方が行数が少なくなり、コンパクトになります。例えば、上記の例で、$a$ と $e$ 以外が NULL の場合、縦持ちは

行番号 属性
属性1 $a$
属性2 $e$

とコンパクトになります。

横持ちを縦持ちに直す

ここから先はSQL で縦横変換まとめ(pivot と unpivot)を参考にしました。

横持ちを縦持ちに直すことを unpivot と言います。SQL では以下のような感じになります。

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の部分のみを抽出したテーブルをそれぞれ作成し、最後に縦に全てくっつけるというイメージです。

縦持ちを横持ちに直す

縦持ちを横持ちに直すことを pivot と言います。SQL では以下のような感じになります。

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種類を整理 を解説します。

ページ上部へ戻る