指定した列の値ごとに行をまとめて集計するSQLの句。
GROUP BY句とは、指定した列の値が同じ行どうしをまとめて1つのグループにし、グループ単位で集計するためのSQLの句です。「○○ごとの合計・平均・件数」を求めたいときに使います。
身近な例で考えると、バラバラのレシートを「店ごとの山」に分けてから、山ごとに合計を出す作業に似ています。まず分け(グループ化)、それから数える・足す(集計)の2段階です。
上のツールで▶ボタンを押すと、キー列(dept)を選び、同じ部署の行をまとめ、各グループに集計関数を適用して「1グループ=1行」の結果になるまでを確認できます。
GROUP BY は集計関数(=複数の値を1つにまとめる関数)とセットで使うのが基本です。代表的な集計関数は次のとおりです。
・COUNT:件数(行数)を数える
・SUM:合計を求める
・AVG:平均を求める
・MAX / MIN:最大値 / 最小値を求める
SELECT dept, COUNT(*), AVG(salary)
FROM employees
GROUP BY dept;
ポイントは、集計関数が「グループ1つにつき1つの値」を返すことです。だから結果はグループの数だけの行になります。また、SELECT に書ける列はGROUP BY で指定した列か、集計関数に限られます。上のツールの集計ステップで、各部署の人数と平均給与が1つずつ計算される様子を確認できます。
GROUP BY でグループ化・集計したあとの結果に条件をつけたいとき、HAVING句を使います。たとえば「人数が3人以上の部署だけ表示する」といった絞り込みです。
GROUP BY dept
HAVING COUNT(*) >= 3;
処理される順番はWHERE(集計前に各行を絞る)→ GROUP BY(まとめる)→ HAVING(集計後のグループを絞る)です。WHERE は1行ずつの条件、HAVING はグループ(集計値)に対する条件、という役割の違いを押さえておきましょう。HAVING の詳しい動きは別ページで扱います。
GROUP BY が「行をまとめる」仕組みはシンプルです。指定した列(キー列)の値が同じ行を1つの束(グループ)にまとめるだけです。たとえば GROUP BY dept なら、dept 列が「営業」の行をすべて1グループ、「開発」の行をすべて1グループとして扱います。
なぜまとめると集計できるのか。グループになった行の集まりに対して集計関数(COUNT・SUM・AVG など)を適用すると、「その束の中の件数」「合計」「平均」をまとめて1つの数値として出せるからです。
・5行あっても営業2行・開発3行の2グループ → 結果は2行になる
・それぞれのグループで「COUNT=行数を数える」「AVG=値を平均する」を実行
・上のツールで「集計」ステップを見ると、各グループ内の salary が1つの平均値に変換される様子を確認できます
身近な例でいうと、クラスを出席番号ではなく「部活ごと」に並べ直して、各部活の人数を数える作業です。並べ直す(グループ化)→数える(集計)の2段階で理解できます。
GROUP BY を使ったとき、SELECT に書ける列にはルールがあります。書けるのは次の2種類だけです。
・GROUP BY で指定した列(グループを代表する値。例:dept)
・集計関数の結果(例:COUNT(*)・AVG(salary))
なぜこのルールがあるのか。GROUP BY でグループ化すると、元の複数の行が「1つのグループ(1行)」に圧縮されます。このときグループ外の列(例:name)はグループ内に複数の値を持つため、「どの値を表示すべきか」が決まりません。
たとえば営業グループには「田中・佐藤」の2人がいます。そこで SELECT name と書いても、「田中」と「佐藤」のどちらを表示すればよいかがわからず、エラーになります。一方 COUNT(*) なら「2人」という1つの値が確定するので、問題なく使えます。