言語
日本語
English

Caution

お使いのブラウザはJavaScriptが無効になっております。
当サイトでは検索などの処理にJavaScriptを使用しています。
より快適にご利用頂くため、JavaScriptを有効にしたうえで当サイトを閲覧することをお勧めいたします。

  1. トップページ
  2. SQL辞典
  3. GROUP BY / HAVING

GROUP BY / HAVING

対応: SQL-92(1992)

行をグループ化して集計するための句です。HAVINGはグループ化後の集計結果に対して条件を指定します。

構文

列でグループ化して集計します。

SELECT グループ列, 集計関数 FROM テーブル名 GROUP BY グループ列;

集計結果にさらに条件を付けます。

SELECT グループ列, 集計関数 FROM テーブル名 GROUP BY グループ列 HAVING 集計条件;

『WHERE』でグループ化前に絞り込み、『HAVING』でグループ化後に絞り込みます。

SELECT グループ列, 集計関数
FROM テーブル名
WHERE 行の絞り込み条件
GROUP BY グループ列
HAVING 集計条件
ORDER BY 並び順;

構文一覧

構文概要
GROUP BY 列名指定した列の値が同じ行をひとまとめにしてグループ化します。SELECT句には集計関数またはGROUP BY指定列のみを記述できます。
HAVING 条件グループ化・集計された後の結果に対して条件を指定します。集計関数を含む条件が書けます。
WHEREグループ化の前に行を絞り込みます。集計関数は使用できません。

サンプルコード

以下の『employees』テーブルを例に説明します。

employees id name department salary retire_date 1 user_a org_a 320000 NULL 2 user_c org_a 280000 NULL 3 user_e org_b 300000 NULL 4 user_b org_b 260000 NULL 5 user_d org_a 350000 2023-03-31 5 rows in set

部署ごとの社員数を取得します。

sample_group_by_having.sql
SELECT department, COUNT(*) AS 人数
FROM employees
GROUP BY department;
+------------+------+
| department | 人数 |
+------------+------+
| org_a      |    3 |
| org_b      |    2 |
+------------+------+
2 rows in set

平均給与が30万円以上の部署のみを取得します(HAVINGで集計後に絞り込み)。

sample_group_by_having.sql
SELECT department, AVG(salary) AS 平均給与
FROM employees
GROUP BY department
HAVING AVG(salary) >= 300000;
+------------+------------+
| department | 平均給与   |
+------------+------------+
| org_a      | 316666.6667 |
+------------+------------+
1 row in set

在籍中の社員のみを対象に、部署ごとの給与合計を取得します。『WHERE』でグループ化前に退職者を除外し、表示します。

sample_group_by_having.sql
SELECT department, COUNT(*) AS 人数, SUM(salary) AS 給与合計
FROM employees
WHERE retire_date IS NULL
GROUP BY department
ORDER BY 給与合計 DESC;
+------------+------+----------+
| department | 人数 | 給与合計 |
+------------+------+----------+
| org_a      |    2 |   600000 |
| org_b      |    2 |   560000 |
+------------+------+----------+
2 rows in set

給与が30万円以上の社員のみを対象に、部署ごとの給与合計を取得します。

sample_group_by_having.sql
SELECT department, COUNT(*) AS 人数, SUM(salary) AS 給与合計
FROM employees
WHERE salary >= 300000
GROUP BY department
ORDER BY 給与合計 DESC;
+------------+------+----------+
| department | 人数 | 給与合計 |
+------------+------+----------+
| org_a      |    2 |   670000 |
| org_b      |    1 |   300000 |
+------------+------+----------+
2 rows in set

データベース別の書き方

『GROUP BY』『HAVING』の基本構文は主要なデータベースで共通して使用できます。

SELECT department, COUNT(*) AS 人数
FROM employees
GROUP BY department
HAVING COUNT(*) >= 1;

MySQLではデフォルトの『sql_mode』に『ONLY_FULL_GROUP_BY』が含まれており、SELECT句にGROUP BYで指定していない列を書くとエラーになります。PostgreSQL も同様に厳密です。古いMySQLではこの制限が無効で、グループ内の不定な値が返される場合がありました。

PostgreSQL では『GROUP BY』の列をSELECT句の列番号で指定できます。

-- PostgreSQL(列番号でGROUP BY)
SELECT department, COUNT(*) AS 人数 FROM employees GROUP BY 1;

概要

『GROUP BY』句を使用する場合、SELECT句に指定できるのはGROUP BYで指定した列と集計関数(COUNT・SUM・AVG・MAX・MINなど)のみです。グループ化していない列を集計関数なしでSELECT句に書くとエラーになります(MySQLのsql_modeによっては動作する場合がありますが非推奨です)。

『WHERE』と『HAVING』の違いは適用タイミングです。『WHERE』はグループ化の前に個々の行を絞り込むため、集計関数は使用できません。『HAVING』はグループ化・集計された後の結果を絞り込むため、『COUNT(*)』や『SUM(salary)』などの集計関数を条件に使用できます。

SELECT文全体の実行順序は『FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT』の順です。この順序を意識すると、どの句でどの条件が使えるかを理解しやすくなります。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。