SQL GROUP BYで複数の行を集計して1行で取得する
SQL
でデータを取得するときに、複数行のデータを集計してデータの合計、平均、件数、最大値などを取得したい場合があります。
以下のようなテーブルがあるとします。
id | first_name | last_name | department_id | height |
---|---|---|---|---|
1 | 一郎 | 山田 | 1 | 170 |
2 | 次郎 | 佐藤 | 2 | 175 |
3 | 三郎 | 田中 | 1 | 185 |
4 | 四郎 | 鈴木 | 2 | 155 |
部署ごと(department_id
ごと) の平均身長、最大身長を取得したいときは以下のようなSQL
になります。
SELECT
department_id,
AVG(height) AS avg_height,
MAX(height) AS max_height
FROM
employee
GROUP BY
department_id
department_id | avg_height | max_height |
---|---|---|
1 | 177.5 | 185 |
2 | 165 | 175 |
部署ごとのデータなので、同一のdepartment_id
のデータは1行に集約して表示する必要があります。
GROUP BY 列名
で集約したい列を指定します。上記例の場合はdepartment_id
ごとに集約したいのでdepartment_id
を指定しています。
集計関数
GROUP BY
で指定した列以外の列をSELECT
句で取得したい場合は、集計関数で集計する必要があります。
なぜなら、以下の2つのデータはdepartment_id
が同じなので1行に集約する必要があるわけですが、department_id
以外の列の値は何を出力すればいいのかわからないからです。
GROUP BY
で指定した列は同じ値のデータが集約される(集約されるデータの値はすべて同じ)ので、集計関数で集計する必要はありません。
id | first_name | last_name | department_id | height |
---|---|---|---|---|
1 | 一郎 | 山田 | 1 | 170 |
3 | 三郎 | 田中 | 1 | 185 |
id | first_name | last_name | department_id | height |
---|---|---|---|---|
? | ? | ? | 1 | ? |
集約されるデータの中での最大のデータを取得したい場合はMAX(列名)
を指定します。
同じように、最小値はMIN
、平均値はAVG
、件数はCOUNT
を使用します。
上記例では平均値と最大値を取得したいので、AVG
とMAX
を使用しています。
集計関数で取得した列名は別名を使用する
SELECT
句で集計関数で取得する項目に別名を指定していないと取得した結果に対してアクセスするときに困ります。
SELECT
department_id,
AVG(height),
MAX(height)
FROM
employee
GROUP BY
department_id
集計関数を使用した列(AVG
とMAX
の列)はアクセスするときに、列名がわからないのでどのようにアクセスすればいいのかがわからないためです。
データベースによっては自動的に列名を付与しますが、どのような列名になるのかがわからないので列名を指定してアクセスできません。
仮にheight
とアクセスした時にAVG
とMAX
のどちらの列のことなのかがわかりません。
そのため、集計関数を使用した場合は列名を指定する必要があります。
GROUP BYで複数列を指定する
複数の列を指定した場合は、指定した列すべての値が同一のデータが集約されます。
集計関数で集計して取得するか、それとも集計単位としてGROUP BY
に指定するか、臨機応変に使い分けていく必要があります。