Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
GROUP BY / HAVING
行をグループ化して集計するための句です。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 | グループ化の前に行を絞り込みます。集計関数は使用できません。 |
サンプルコード
-- 部署ごとの社員数を取得します。 SELECT department, COUNT(*) AS 人数 FROM employees GROUP BY department; -- 平均給与が30万円以上の部署のみを取得します(HAVINGで集計後に絞り込み)。 SELECT department, AVG(salary) AS 平均給与 FROM employees GROUP BY department HAVING AVG(salary) >= 300000; -- 在籍中の社員のみを対象に、部署ごとの給与合計を取得します。 -- WHERE でグループ化前に退職者を除外し、HAVING で2人以上の部署を絞り込みます。 SELECT department, COUNT(*) AS 人数, SUM(salary) AS 給与合計 FROM employees WHERE retire_date IS NULL GROUP BY department HAVING COUNT(*) >= 2 ORDER BY 給与合計 DESC; -- 商品カテゴリごとの売上合計を取得します。 SELECT category, SUM(price * quantity) AS 売上合計 FROM order_items GROUP BY category ORDER BY 売上合計 DESC;
実行結果
-- SELECT department, COUNT(*) AS 人数, SUM(salary) AS 給与合計 -- FROM employees WHERE retire_date IS NULL GROUP BY department HAVING COUNT(*) >= 2 -- ORDER BY 給与合計 DESC; の結果例 -- +----------+------+----------+ -- | department | 人数 | 給与合計 | -- +----------+------+----------+ -- | 開発部 | 5 | 1500000 | -- | 営業部 | 4 | 1160000 | -- +----------+------+----------+
データベース別の書き方
『GROUP BY』『HAVING』の基本構文は主要なデータベースで共通して使用できます。
SELECT department, COUNT(*) AS 人数 FROM employees GROUP BY department HAVING COUNT(*) >= 2;
MySQLではデフォルトの『sql_mode』に『ONLY_FULL_GROUP_BY』が含まれており、SELECT句にGROUP BYで指定していない列を書くとエラーになります。PostgreSQL・Oracle・SQL Server も同様に厳密です。古い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』の順です。この順序を意識すると、どの句でどの条件が使えるかを理解しやすくなります。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。