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に指定するか、臨機応変に使い分けていく必要があります。