トップページ > 基礎知識 > レコードを縦並びから横並びにする方法

レコードを縦並びから横並びにする方法

データベースに入るレコードは横方向の列には項目(カラム)が並び、縦方向の行には実際のデータ(レコード)が並ぶのが一般的な考え方だが、この縦に並んでいるレコードを横並びに変更する方法を紹介する。

レコードを横並びにする必要性

縦に並んでいるレコードを横並びにしたい場合は、特定の人や物などに対して付帯する情報がレコードごとに格納されている場合である。
例えば下表のように個人別の成績表を一つのテーブルにまとめていたとする。

 氏名  | 国語点数 | 算数点数 | 社会点数
-------+----------+----------+----------
 AA AA |       81 |       74 |       85
 BB BB |       92 |       76 |       86
 CC CC |       73 |       82 |       90

この表の特徴としては個人の成績を一行で表すことができ、登録や更新の操作は氏名をキーにすることで操作が非常に楽であるが、科目に増減があるとカラムの増減を行う必要が出てくる。
ここで科目もテーブルの正規化を行うと一行あたりのレコードには「誰が」「どの科目」「何点だったか」を入れるようにすると科目の増減に対応することができる。

 氏名  | 科目 | 点数 
-------+------+------
 AA AA | 国語 |   81
 AA AA | 算数 |   74
 AA AA | 社会 |   85
 BB BB | 国語 |   92
 ・
 ・

このように一つのテーブルに同じ人のレコードが複数入っている場合、一つ目のテーブルのように表示するのがレコードの横並びである。

レコードを横並びにしたいテーブルの内容

レコードを横並びにしたいテーブルが下表とする。
上記の例のように科目ごとの点数をテーブル「t_tensu」に格納するものとし、生徒を格納するテーブル「t_user」に 2 人いたとする。
科目はテーブル「t_option」に入れている想定である。
さらに user_id = 1 の情報だけが一つのテーブルに複数行テーブルに入っているものとし、user_id = 2 の情報は入っていないものとする。

table=> SELECT * FROM t_tensu ORDER BY user_id, option_id ASC;
 user_id | option_id | value
---------+-----------+-------
       1 |         1 |    81
       1 |         2 |    74
       1 |         3 |    85

上記の SQL ではテーブルに格納されているレコードしか表示しないため、user_id = 2 の情報は表示されない。

レコードを横並びにする SQL

上記のテーブル「t_tensu」に縦並びになっているレコードを横並びにするには次の SQL で実現できる。
縦並びに該当するのはテーブル「t_user」の生徒するために横並びにした各人の点数を JOIN で結合している。
実際にレコードを横並びにしているのは max (CASE WHEN *** THEN *** END) の箇所である。

SELECT t1.user_id, t4.set_01, t4.set_02, t4.set_03
FROM t_user AS t1
LEFT JOIN 
(SELECT 
    t2.user_id,
    max(CASE WHEN t2.option_id = '1' THEN t2.set_value END) AS set_01,
    max(CASE WHEN t2.option_id = '2' THEN t2.set_value END) AS set_02,
    max(CASE WHEN t2.option_id = '3' THEN t2.set_value END) AS set_03
FROM t_option AS t3
LEFT JOIN t_tensu AS t2
ON t2.option_id = t3.option_id
GROUP BY t2.user_id ) AS t4
ON t1.user_id = t4.user_id
ORDER BY t1.user_id ASC;

 user_id | set_01 | set_02 | set_03
---------+--------+--------+--------
       1 |     81 |     74 |     85
       2 |        |        |

関連記事

@webolve をフォローしてください