Loading
  • LIGHT

  • DARK

ROUTE

ルートゼロの
アクティビティ

GROUP BY使い方完全解説|SQLエラー・WHERE HAVINGの違いは?

3

GROUP BYで迷わない──WHEREとHAVING、どちらで絞る?現場で差がつく“実行順序”理解法

GROUP BYで集計しようとしたら、エラー?思った値が出ない?
…そんな“つまずき”に、私たちは何度も出くわします。
なぜWHEREHAVINGの使い分けで迷うのか?
──答えは「SQLの実行順序」を“腹落ち”で理解できていないからです。
私たち開発者が現場でハマる理由と、明日から使える“脱落しないGROUP BY”テクを図解と共に解説します。

用語解説:GROUP BY
SQLでデータを特定の列ごとにまとめて集計するための構文。売上や件数など、グループ単位で計算したいときに使う。

用語解説:WHERE
SQLでデータを抽出・絞り込みするための条件指定句。グループ化や集計の前段階で使う。

用語解説:HAVING
GROUP BYでグループ化・集計した後のデータに対して条件を指定し、さらに絞り込むための句。

用語解説:SQL
データベースを操作するための言語。データの検索・集計・更新・削除などを行う。

(SQLの基本やSELECT文の実行順については『初心者向けSQL講座|SELECT文の書き方と実行順を完全解説』をご参照ください)


GROUP BYとは?――生データを“まとめて要約”するSQLの第一歩

GROUP BYは「特定の列ごとにデータをグループ化し、集計する」ためのSQL句です。
たとえば、下記の売上テーブルを例に見てみましょう。

用語解説:テーブル
データベース内でデータを行と列で管理するための表。Excelの表のようなイメージ。


| order_id | order_date | product_category | total_price |
|----------|------------|------------------|-------------|
| 1        | 2023-04-01 | 書籍             | 2000        |
| 2        | 2023-04-02 | 家電             | 50000       |
| 3        | 2023-04-03 | 書籍             | 1500        |
| 4        | 2023-05-10 | 食品             | 500         |
| 5        | 2023-05-12 | 家電             | 30000       |

このままでは「カテゴリ別の売上合計」が見えません。
GROUP BYなら、「書籍」「家電」…のカテゴリごとにまとめ、合計・件数などをすぐ算出できます。

用語解説:集計関数(SUM, COUNTなど)
データの合計(SUM)、件数(COUNT)、平均(AVG)などを計算するSQLの関数。GROUP BYと組み合わせて使う。

(SQLの集計関数やNULLの扱いについては『SQL NULL完全攻略|IS NULL・COALESCEの使い分けとDB別バグ防止術5選』もご参照ください)

“バラバラなデータを“意味あるかたまり”に整理し、集計する”
これがGROUP BYの本質です。


1. なぜ混乱?WHEREとHAVINGの違いは「SQLの処理順」にあり

私たちがつまずきやすいのが、WHEREとHAVINGの使い分け
この違い、どう説明できますか?
ポイントは「SQLが内部でどんな順番で処理されるか」です。
実は、書いた通りの順ではなく、下記の“7ステップ”で実行されています。

【図解】SQLクエリの7段階処理フロー

  • FROM … どのテーブルか
  • JOIN … 必要なら結合
  • WHEREグループ化前に元データを絞り込む
  • GROUP BY … 指定列でグループ化
  • HAVINGグループ化後の集計値で絞り込む
  • SELECT … 何を出すか(集計もここ)
  • ORDER BY … 並び順を決める

用語解説:FROM
どのテーブルからデータを取得するかを指定するSQL句。

用語解説:JOIN
複数のテーブルを結合し、関連するデータをまとめて取得するためのSQL句。

用語解説:SELECT
どの列(項目)を出力するかを指定するSQL句。集計関数もここで使う。

用語解説:ORDER BY
結果の並び順を指定するSQL句。昇順・降順などを指定できる。

処理の流れイメージ図をここに
“どのタイミングでデータを絞るか”が、WHEREとHAVINGの決定的な差です。

  • WHERE集計・グループ化前SUM()COUNT()など集計関数は使えない
  • HAVINGグループ化後SUM()など集計済みの値で絞り込む

(WHERE・HAVING・JOINの違いと実践的な使い分けは『SQL IN・EXISTS・JOINの違い徹底解説|安全で速い選び方と実践7チェック』もご参照ください)

料理で例えると…
WHEREは「材料の下ごしらえ」。
HAVINGは「完成した料理の合格チェック」です。


2. これで腹落ち!現場でよく使うGROUP BYパターン3選

実際に、売上データで「GROUP BYの基本→応用→HAVING絞り込み」まで流れを追いましょう。

2-1. 基本:「カテゴリごとに件数」を出す(COUNT)


SELECT
    product_category,
    COUNT(order_id) AS order_count
FROM
    sales
GROUP BY
    product_category;

実行例:


| product_category | order_count |
|------------------|------------|
| 書籍             | 2          |
| 家電             | 2          |
| 食品             | 1          |
  • GROUP BYで「書籍・家電・食品」ごとにグループ
  • COUNTで各グループの件数を取得

2-2. 応用:「カテゴリ・月ごとの売上合計」を出す(複数列GROUP BY, SUM)


SELECT
    product_category,
    STRFTIME('%Y-%m', order_date) AS sales_month, -- SQLiteの場合
    SUM(total_price) AS monthly_sales
FROM
    sales
GROUP BY
    product_category, sales_month;

用語解説:複数列GROUP BY
GROUP BYで2つ以上の列を指定すると、「カテゴリ×月」など複数軸でグループ化できる。

実行例:


| product_category | sales_month | monthly_sales |
|------------------|-------------|--------------|
| 書籍             | 2023-04     | 3500         |
| 家電             | 2023-04     | 50000        |
| 家電             | 2023-05     | 30000        |
| 食品             | 2023-05     | 500          |

複数列でグループ化すれば、「カテゴリ×月」単位の集計も簡単です。


2-3. 実践:売上が10万円以上のカテゴリだけ抽出(HAVING)


SELECT
    product_category,
    SUM(total_price) AS total_sales
FROM
    sales
GROUP BY
    product_category
HAVING
    SUM(total_price) >= 100000;
  • GROUP BY後の集計値(ここではSUM)で絞るなら、HAVINGが必須
  • WHEREでSUMを書くとエラーになる理由は、“集計前”だから

3. GROUP BYでよく出るエラー──原因と解決策

「SELECTに書いた列がGROUP BYにない」
「WHEREでSUM()したらエラー」
…私たちが現場で“焦る”ポイントを整理します。

3-1. SELECTリストの列がGROUP BYに無い


-- ❌ エラー例
SELECT product_category, product_name
FROM sales
GROUP BY product_category;

用語解説:SELECTリスト
SELECT句で指定した出力対象の列の一覧。GROUP BYに含まれない列は集約関数でまとめる必要がある。

原因:
「書籍」グループの中に複数のproduct_nameがあり、どれを出すか決められないから。

解決:


-- ✅ product_nameもグループ化
SELECT product_category, product_name
FROM sales
GROUP BY product_category, product_name;

3-2. WHERE句で集計関数を使っている


-- ❌ エラー例
SELECT product_category, SUM(total_price)
FROM sales
WHERE SUM(total_price) > 10000
GROUP BY product_category;

用語解説:WHERE句と集計関数の関係
WHERE句はグループ化前のデータにしか使えず、SUMやCOUNTなどの集計関数はHAVING句で使う。

原因:
WHERE句は“グループ化前”のデータにしかアクセスできず、SUM値はまだ無いから。

解決:


-- ✅ HAVINGで絞る
SELECT product_category, SUM(total_price) AS total_sales
FROM sales
GROUP BY product_category
HAVING SUM(total_price) > 10000;

4. “GROUP BY迷子”を脱却するための3ポイントまとめ

  • WHEREは素材選び:グループ化のデータを絞り込む
  • GROUP BYで束ねる:指定した列でグループ化する
  • HAVINGは完成品選び:グループ化の集計値で絞る

これを押さえれば、SELECTに何を書く?WHERE?HAVING?…で迷うことはなくなります。

ぜひコードをコピペして、まずは動かしてみてください。


FAQ

  • Q. NULLを含む列をGROUP BYすると?
    NULLも1つの独立したグループになります。
  • Q. GROUP BYとウィンドウ関数(PARTITION BY)の違いは?

    GROUP BYは集約して行数が減るウィンドウ関数は元の行数そのままで集計値が付与されます。
  • Q. HAVING句で複数条件は?
    AND/ORで複数条件可
    例:HAVING SUM(total_price) > 10000 AND COUNT(order_id) >= 2
  • Q. GROUP BYとDISTINCTの使い分けは?
    DISTINCTは重複除去、GROUP BYは集計やグループ単位で計算したいとき。
  • Q. 集計値で並び替えたい
    ORDER BY SUM(total_price) DESC などでOK。
  • Q. なぜGROUP BYの後にWHEREは使えない?
    SQLはWHERE→GROUP BYの順で処理
    つまり、“未来の値”で元データを絞ることはできません

用語解説:NULL
データが存在しないことを示す特別な値。GROUP BYではNULLも1つのグループとして扱われる。

用語解説:ウィンドウ関数(PARTITION BY)
元の行数を保ったまま、グループごとの集計値を各行に付与できるSQLの機能。

用語解説:DISTINCT
重複するデータを除外し、一意な値だけを抽出するSQLのキーワード。

(DISTINCT・GROUP BY・ROW_NUMBERの違いは『SQL重複除外のベストプラクティス徹底比較|DISTINCT・GROUP BY・ROW_NUMBERの違いは?』もご参照ください)


「SQLの実行順序」を知れば、もうGROUP BYは怖くない──明日から集計クエリを“自信を持って”書けるようになります。


もっとルートゼロを知りたいなら

DISCOVER MORE