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』テーブルを例に説明します。
部署ごとの社員数を取得します。
sample_group_by_having.sql
SELECT department, COUNT(*) AS 人数 FROM employees GROUP BY department;
+--------------------+------+ | department | 人数 | +--------------------+------+ | 堂島組 | 1 | | 真島組 | 1 | | スカイファイナンス | 1 | | 錦山組 | 1 | | 冴島組 | 1 | +--------------------+------+ 5 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 | 平均給与 | +--------------------+----------+ | 堂島組 | 320000 | | スカイファイナンス | 300000 | | 冴島組 | 350000 | +--------------------+----------+ 3 rows 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 | 人数 | 給与合計 | +--------------------+------+----------+ | 堂島組 | 1 | 320000 | | スカイファイナンス | 1 | 300000 | | 真島組 | 1 | 280000 | | 錦山組 | 1 | 260000 | +--------------------+------+----------+ 4 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 | 人数 | 給与合計 | +--------------------+------+----------+ | 冴島組 | 1 | 350000 | | 堂島組 | 1 | 320000 | | スカイファイナンス | 1 | 300000 | +--------------------+------+----------+ 3 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』の順です。この順序を意識すると、どの句でどの条件が使えるかを理解しやすくなります。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。