【SQL第6回】グループ化と集計:GROUP BY

SQL基礎講座 全10回(第6回)

【SQL第6回】グループ化と集計:GROUP BY

データを「性別ごと」「商品カテゴリごと」といった特定のグループに分類し、グループごとの集計値を一発で計算する「GROUP BY句」と、集計結果に対する絞り込み「HAVING句」の正しい書き方を習得します。

📌 SQL講座ロードマップ一覧(クリックで移動)

1. カテゴリ別にデータをまとめる GROUP BY 句

第5回では、テーブル全体の売上合計金額を出しました。しかし、実務では「支店ごとの売上合計」や「男女別の平均年齢」など、特定の項目ごとに小計を出したいケースが圧倒的に多いです。

このグループ分け集計を担当するのが `GROUP BY句` です。

`GROUP BY グループ化するカラム名` と記述することで、同一のデータ値を持つレコードが自動的にグループ化され、各グループに対して `SUM` や `COUNT` などの集計処理が並列して実行されます。

2. 初心者が陥る GROUP BY の厳格なルール

`GROUP BY` を使う時、初心者が必ずと言っていいほど直面するエラーがあります。それは、**「グループ化したカラムと、集計関数以外のカラムを SELECT に書いてはならない」**というルールです。

⚠️ エラーになるクエリの典型例

SELECT name, address, SUM(amount) FROM orders GROUP BY address;
(※住所ごとに集計しているのに、各住所に含まれる複数の個人名「name」のうち誰を出力すればいいかRDBMSが判断できないため、エラーになります。)

3. 集計後の結果をさらに絞り込む HAVING 句

第3回で学んだ `WHERE` 句は、「集計計算を行う**前**の元のデータ行」を絞り込むものでした。

これに対し、「集計計算を完了した**後**の結果(例:注文数が100件以上の部署、など)」に対して絞り込みを掛けたい場合は、WHEREではなく `HAVING句` を使用します。

4. グループ集計とHAVINGによる抽出SQLクエリ

以下のクエリは、部署ごとに社員の平均給与を計算し、さらに平均給与が30万円以上の部署のみに結果を絞り込む高度な実戦コード例です。

groupby_having.sql
-- 部署ごとの平均給与を集計し、平均30万以上の部署のみを抽出
SELECT
    department AS 部署名,
    AVG(salary) AS 平均給与
FROM
    employees
GROUP BY
    department
HAVING
    AVG(salary) >= 300000;

📌 WHERE と HAVING の記述順序

SQL句の追加により、正しい記述順序は以下のようになります:
**`SELECT ➔ FROM ➔ WHERE ➔ GROUP BY ➔ HAVING ➔ ORDER BY ➔ LIMIT`**
WHERE句が最初に行(レコード)の足切りを行い、残った行をGROUP BYがグループ化し、集計した結果をHAVINGがさらに絞り込む、という実行の流れ(実行順序)をしっかりとイメージしましょう。

✍️ 第6回 理解度チェック(問題)

SQLで「WHERE句」は集計を行う前の行の絞り込みに使われますが、「GROUP BYでグループ集計した後の結果値」に対して条件絞り込みを適用したい場合に使用する句の名前は何でしょうか?

※この問題の解答と解説は、ページ最下部(まとめの前)に掲載しています。

5. まとめと次回予告

第6回の講義はお疲れ様でした!今回の重要ポイントを振り返りましょう。

  • `GROUP BY` を使って特定のカラム値ごとにデータをグループ化して集計できる。
  • SELECTには、グループ化したカラムと集計関数以外の任意のカラムを記述することはできない。
  • 集計完了後の結果を絞り込む条件指定には、WHEREではなく `HAVING` 句を使用する。

次回(第7回)は、関係データベース(RDB)の最大の醍醐味である、複数のテーブルを共通のキーを頼りに合体させて情報を取得する「複数テーブルの結合:INNER JOIN」について学びます。お楽しみに!

🔑 第6回 理解度チェックの解答と解説

【解説】

正解は **`HAVING`** (または `HAVING句`)です。 `WHERE` 句はグループ化される前の各行のデータを判定し、`HAVING` 句はグループ化されて集計(`SUM` や `COUNT` など)された計算後の数値を評価して絞り込みを行うため、それぞれが評価されるタイミングが明確に異なります。