SQLでグループ化して集計したい場合はGROUP BY句を使います。
本記事では、GROUP BY句の使い方から、COUNT関数などの集約関数との併用方法、WHERE句やHAVING句との合わせ技についても具体例を交えて解説しています。
目次
GROUP BY句の使い方
GROUP BYはデータをグルーピングするために使います。チームごとの得点を算出したり、カテゴリーごとの売上を算出するなど使用用途は様々です。
使い方も難しくなく、基本構文は下記です。
SELECT カラム名
FROM テーブル名
GROUP BY グループ化するカラム名;
GROUP BY カラム名
で特定のカラムを起点としてグループ化を行います。
1点注意すべき点は、SELECT句にはGROUP BY句で指定したカラムか集約関数(COUNT・SUM・MAXなど)のみ指定できるということです。
例えば、GROUP BY
でid
しか指定していないのに、SELECT句でid
とemail
を指定することはできません。GROUP BY
でid
だけを指定しているなら、SELECT句で指定できるのもidだけです。
サンプルデータ
下記のとおり、usersテーブルを用意します。
id | name | age | address |
---|---|---|---|
1 | 山田 | 25 | 東京都 |
2 | 鈴木 | 34 | 神奈川県 |
3 | 佐藤 | 29 | 大阪府 |
4 | 佐々木 | 47 | 東京都 |
5 | 大野 | 25 | 東京都 |
6 | 小池 | 34 | 大阪府 |
カラムを指定してグループ化する
では、サンプルデータを元にグループ化を行ってみましょう。
検索クエリ
usersテーブルを居住地ごとでグループ化する
SELECT address
FROM users
GROUP BY address;
GROUP BY address
で居住地ごとにグループ化を行なっています。
実行結果
address |
---|
神奈川県 |
東京都 |
大阪府 |
グループ化されて重複がないように居住地情報を取得できました。
複数カラムを指定する
次に、複数カラムを指定してグループ化する方法を見ていきます。
検索クエリ
usersテーブルの名前と居住地の組み合わせでグループ化する
SELECT age, address
FROM users
GROUP BY age, address;
GROUP BY age, address
とすることで、ageカラムとaddressカラムの組み合わせでグループ化されます。
実行結果
age | address |
---|---|
25 | 東京都 |
29 | 大阪府 |
34 | 大阪府 |
34 | 神奈川県 |
47 | 東京都 |
nameカラムの値とaddressカラムの値が一致するレコードは統合されました。年齢が34歳のレコードは2つありますが、居住地が異なるためグループ化されていません。
グループ化して数を数える(COUNT関数)
次に、グループ化した上でそれぞれのグループに存在するレコードの数をカウントする方法を見ていきます。
数を数えるためには、集約関数の一つであるCOUNT関数を使います。
検索クエリ
usersテーブルを居住地ごとでグループ化し、グループごとのレコード数を取得する
SELECT address, COUNT(*)
FROM users
GROUP BY address;
GROUP BY address
で居住地ごとにグループ化した上で、COUNT(*)
でレコードの数を取得しています。
COUNT(*)
はGROUP BY
では指定していませんが、集約関数なのでSELECT句で使えます。
実行結果
address | COUNT(*) |
---|---|
大阪府 | 2 |
東京都 | 3 |
神奈川県 | 1 |
居住地ごとにグループ化した上で、それぞれのレコードの数を取得できました。
COUNT関数以外にもSUM関数・MAX関数・MIN関数・AVG関数などの集約関数を使って集計が可能です。
【SQL】SUM関数を使って指定カラムの合計値を求める SQLのMAX関数(最大値)・MIN(最小値)の使い方を徹底解説 【SQL】AVG関数で平均値を求める方法を分かりやすく解説条件指定をする
WHERE句とHAVING句はどちらも検索条件を指定することができます。
この2つの違いと、それぞれの使い方を見ていきましょう。
GROUP BY句とWHERE句の違い
違いはクエリが実行される順番にあります。
- WHERE句・・GROUP BY句の前に実行される
- HAVING句・・GROUP BY句の後に実行される
WHERE句はグループ化する前に条件を指定できるのに対して、HAVING句はグループ化した後に条件指定ができます。
初心者が最初は困惑する部分でもあるので、繰り返しになりますが実行される順番が違うという点をとにかく覚えておきましょう!
グループ化する前に条件指定をする方法(WHERE句を使う)
グループ化する際にWHERE句を使って条件指定する場合を見ていきましょう。
検索クエリ
年齢が30歳以下の人に絞った上で、居住地ごとにグループ化する
SELECT address
FROM users
WHERE age =< 30
GROUP BY address;
GROUP BY address
と居住地でグループ化する前に、WHERE age =< 30
と条件指定を行っています。
実行結果
address |
---|
大阪府 |
東京都 |
居住地が神奈川県の人は年齢が30歳より大きいため、除外されていることが分かります。
グループ化した後に条件指定をする方法(HAVING句を使う)
次に、グループ化する際にHAVING句を使って条件指定する場合を見ていきましょう。
検索クエリ
居住地ごとにグループ化し、最年少の人が30歳を超えているグループのみ取得する
SELECT address, MIN(age)
FROM users
GROUP BY address
HAVING MIN(age) > 30;
GROUP BY address
と居住地ごとでグループ化した上で、HAVING MIN(age) > 30
と条件指定を行っています。特定カラムの最小値を取得するにはMIN関数を使用します。
また、MIN(age)
はGROUP BY
では指定していませんが、集約関数なのでSELECT句で使えます。
実行結果
address | MIN(age) |
---|---|
神奈川県 | 34 |
東京都、大阪府の人の最年少は30歳を下回っているため、検索結果から除外されていることが分かります。
このように、集約関数(MIN関数・COUNT関数・SUM関数・AVG関数など)を使用する際にHAVING句を使うことが多いです。
内容のまとめ
- GROUP BY句は特定のカラムでグループ化する時に使う
- GROUP BY句の基本構文は
SELECT カラム名 FROM テーブル名 GROUP BY グループ化するカラム名
- SELECT句にはGROUP BY句で指定したカラムか集約関数(COUNT・SUM・MAXなど)のみ指定できる
- 複数カラムでグループ化する際は、
GROUP BY カラム名1, カラム名2
とカンマ区切りでカラムを指定する - グループごとのレコード数を取得する場合はCOUNT関数を使う
- 条件指定にはWHERE句とHAVING句の2つがあり、違いはクエリが実行される順番にある
- WHERE句はGROUP BY句の前に実行されるのに対して、HAVING句はGROUP BY句の後に実行される