よっしーの私的空間

機械学習を中心に興味のあることについて更新します

縦持ちデータを横持ちデータに変換する方法(SQL)

前回はPythonのPandasで縦持ちデータを横持ちにする方法についてまとめましたが、今回はSQLです。PostgreSQLで実行した方法ですが、たぶんOracleMySQLでも動くと思います。動かったなかったらごめんなさい。 縦持ちデータを横持ちデータに変換する方法についてはこちらにまとめています。

1.実施内容(概要)

SQLで以下のような縦持ちデータを

氏名 科目 点数
A君 数学 100
A君 国語 70
A君 英語 60
A君 ドイツ語 60
B君 数学 60
B君 国語 50
B君 英語 50
B君 アラビア語 60

以下のような横持ちデータに変換します。

氏名 数学 国語 英語 ドイツ語 アラビア語
A君 100 70 60 60 NaN
B君 60 50 50 NaN 60

2.SQL

select
 name,
 max(case subject when '数学' then score else null end) as math_score,
 max(case subject when '国語' then score else null end) as literature_score,
 max(case subject when '英語' then score else null end) as english_score,
 max(case subject when 'ドイツ語' then score else null end) as german_score,
 max(case subject when 'アラビア語' then score else null end) as arabic_score
from t_score_verticle
group by name;

3.解説

上記のmaxが一見謎ですが、これはgroup byを使用するために必要になります。縦持ちデータを横持ちデータに変換する際に、データをnameでgroup byするのですが、selectとgroup byは同じキーを指定しないと構文エラーになってしまうので、回避策としてmaxやsum等を指定することになります。
蛇足ですが、maxやsumを指定することでどのような挙動になるかは、以下の例を見ていただければ分かるかと思います。

例)A君・数学のデータが2行ある場合

氏名 科目 点数
A君 数学 100
A君 数学 120
A君 国語 70
B君 数学 60
B君 国語 50

先に説明したSQLを実行すると、以下のような結果が返ってきます。

氏名 数学 国語
A君 120 70
B君 60 50