zukucode
主にWEB関連の情報を技術メモとして発信しています。

SQL GROUP BYで複数の行を集計して1行で取得する

SQLでデータを取得するときに、複数行のデータを集計してデータの合計、平均、件数、最大値などを取得したい場合があります。

以下のようなテーブルがあるとします。

employee(社員)
idfirst_namelast_namedepartment_idheight
1一郎山田1170
2次郎佐藤2175
3三郎田中1185
4四郎鈴木2155

部署ごと(department_idごと) の平均身長、最大身長を取得したいときは以下のようなSQLになります。

SELECT
  department_id,
  AVG(height) AS avg_height,
  MAX(height) AS max_height
FROM
  employee
GROUP BY
  department_id
取得結果
department_idavg_heightmax_height
1177.5185
2165175

部署ごとのデータなので、同一のdepartment_idのデータは1行に集約して表示する必要があります。

GROUP BY 列名で集約したい列を指定します。上記例の場合はdepartment_idごとに集約したいのでdepartment_idを指定しています。

集計関数

GROUP BYで指定した列以外の列をSELECT句で取得したい場合は、集計関数で集計する必要があります。

なぜなら、以下の2つのデータはdepartment_idが同じなので1行に集約する必要があるわけですが、department_id以外の列の値は何を出力すればいいのかわからないからです。

GROUP BYで指定した列は同じ値のデータが集約される(集約されるデータの値はすべて同じ)ので、集計関数で集計する必要はありません。

employee
idfirst_namelast_namedepartment_idheight
1一郎山田1170
3三郎田中1185
集約結果
idfirst_namelast_namedepartment_idheight
???1?

集約されるデータの中での最大のデータを取得したい場合はMAX(列名)を指定します。

同じように、最小値はMIN、平均値はAVG、件数はCOUNTを使用します。

上記例では平均値と最大値を取得したいので、AVGMAXを使用しています。

集計関数で取得した列名は別名を使用する

SELECT句で集計関数で取得する項目に別名を指定していないと取得した結果に対してアクセスするときに困ります。

SELECT
  department_id,
  AVG(height),
  MAX(height)
FROM
  employee
GROUP BY
  department_id

集計関数を使用した列(AVGMAXの列)はアクセスするときに、列名がわからないのでどのようにアクセスすればいいのかがわからないためです。

データベースによっては自動的に列名を付与しますが、どのような列名になるのかがわからないので列名を指定してアクセスできません。

仮にheightとアクセスした時にAVGMAXのどちらの列のことなのかがわかりません。

そのため、集計関数を使用した場合は列名を指定する必要があります。

GROUP BYで複数列を指定する

複数の列を指定した場合は、指定した列すべての値が同一のデータが集約されます。

集計関数で集計して取得するか、それとも集計単位としてGROUP BYに指定するか、臨機応変に使い分けていく必要があります。


関連記事