SQLのGROUP BYとHAVINGの違い|集計条件を初心者向けに解説
この記事でわかること
- SQLのGROUP BYが何をまとめるための句なのか
- HAVINGとWHEREの違い
- COUNTやSUMで集計した結果を条件で絞る考え方
- 初学者が間違えやすい集計SQLの書き方
- 実務で集計条件を整理するときの確認手順
結論・重要ポイント
- GROUP BYは、同じ値を持つ行をグループにまとめ、COUNTやSUMなどの集計関数で集計するために使います。
- WHEREはグループ化する前の行を絞り込み、HAVINGはグループ化した後の集計結果を絞り込みます。
- COUNT(*) > 5のように、集計後の値で条件を付けたい場合はHAVINGを使います。
- SELECTに出す通常の列は、基本的にGROUP BYへ含めるか、集計関数の中で使う必要があります。
- GROUP BYは並び順を保証しないため、表示順を決めたい場合はORDER BYも指定します。
対象読者と前提知識
この記事は、SQLで一覧取得はできるようになったものの、件数や合計を分類ごとに出すところで迷っている初学者向けです。
前提知識は、SELECT、FROM、WHEREの基本が分かる程度で問題ありません。ここでは、売上テーブルを例に、集計する単位と条件の順番を中心に説明します。
3人による授業形式の会話
生徒うみちゃん
売上データで、カテゴリごとの件数を出したいんだけど、WHEREでカテゴリを指定すれば集計できるってこと?
MAO先生
結論から言うと、カテゴリごとにまとめるならGROUP BYを使うのです。WHEREは行を先に絞るための条件で、まとめる単位そのものを作る役割ではありません。
生徒うみちゃん
じゃあ、GROUP BY categoryって書くと、同じカテゴリの行がひとつのまとまりになるんだね!
MAO先生
その通りです。そこへ**COUNT(*)**を組み合わせると、カテゴリごとの行数を数えられます。集計したい単位を先に決めると、SQLが読みやすくなりますよ。
生徒りくちゃん
集計したあとで、件数が5件以上のカテゴリだけ表示したい場合は、WHERE COUNT(*) >= 5と書けばよいのでしょうか?
MAO先生
そこは大切な注意点です。WHEREの段階では、まだCOUNT()の結果がありません。集計後の条件はHAVING COUNT() >= 5と書くのです。
生徒うみちゃん
なるほど。先に材料を選ぶのがWHEREで、できあがった集計結果を選ぶのがHAVINGじゃん!
MAO先生
とてもよい整理です。実は、実務ではWHEREとHAVINGを両方使うこともあります。例えば、今年の売上行だけをWHEREで選び、そのあとカテゴリ別合計が一定以上のものだけをHAVINGで残します。
生徒りくちゃん
SELECTに商品名も出したい場合、カテゴリでグループ化しているのに商品名をそのまま出すと、どの商品名を表示すればよいか曖昧になりませんか?
MAO先生
よく気づきましたね!基本は、SELECTに出す通常の列はGROUP BYに含めるか、MINやMAXなどの集計関数で扱います。グループの代表が曖昧な列をそのまま出さないのが安全です。
生徒うみちゃん
つまり、何でまとめるか、何を数えるか、どの集計結果を残すかを分けて考えればいいってことだね!
生徒りくちゃん
最後に並び順が必要なら、ORDER BYで明示するということですね。GROUP BYだけで並ぶと思い込まないようにします。
コード・操作手順・具体例
1. 例で使う売上テーブルを決める
次のようなsalesテーブルがあるとします。
CREATE TABLE sales (
id INTEGER,
category TEXT,
amount INTEGER,
sold_at DATE
);
サンプル行のイメージは次のとおりです。
id | category | amount | sold_at
1 | book | 1200 | 2026-07-01
2 | pen | 300 | 2026-07-01
3 | book | 1800 | 2026-07-02
4 | note | 500 | 2026-07-02
5 | pen | 250 | 2026-07-03
2. カテゴリごとの件数を数える
GROUP BYでカテゴリごとにまとめ、**COUNT(*)**で行数を数えます。
SELECT
category,
COUNT(*) AS order_count
FROM sales
GROUP BY category;
このSQLは、categoryの値が同じ行をまとめて、カテゴリごとの件数を返します。
3. 集計前の行をWHEREで絞る
特定の日付以降の売上だけを対象にしたい場合は、グループ化の前にWHEREで行を絞ります。
SELECT
category,
COUNT(*) AS order_count
FROM sales
WHERE sold_at >= DATE '2026-07-01'
GROUP BY category;
WHEREは、集計する前の材料を選ぶ条件です。対象期間、対象店舗、削除済みでない行など、行単位で判断できる条件に向いています。
4. 集計後の結果をHAVINGで絞る
カテゴリごとに数えたあと、件数が2件以上のカテゴリだけ残す例です。
SELECT
category,
COUNT(*) AS order_count
FROM sales
GROUP BY category
HAVING COUNT(*) >= 2;
HAVINGは、グループ化された結果に対する条件です。COUNT(*)、SUM(amount)、**AVG(amount)**など、集計後の値で判断したいときに使います。
5. WHEREとHAVINGを両方使う
実務では、集計前の条件と集計後の条件を分けて書くと読みやすくなります。
SELECT
category,
SUM(amount) AS total_amount
FROM sales
WHERE sold_at >= DATE '2026-07-01'
GROUP BY category
HAVING SUM(amount) >= 1000
ORDER BY total_amount DESC;
この例では、先に対象期間の行だけを選び、そのあとカテゴリ別の合計金額が1000以上のカテゴリだけを残し、最後に合計金額の大きい順へ並べています。
※**DATE ‘2026-07-01’**の書き方はデータベース製品によって対応差があります。利用している製品の公式ドキュメントに合わせて日付リテラルや型変換を書いてください。
よくある誤解や失敗
HAVINGをWHEREの代わりに何でも使ってしまう
集計前に絞れる条件までHAVINGへ入れると、SQLの意図が分かりにくくなります。行単位で判断できる条件は、基本的にWHEREへ置きます。
SELECT
category,
COUNT(*) AS order_count
FROM sales
GROUP BY category
HAVING category = 'book';
上の例は、多くの場合、次のようにWHEREへ置いた方が意図が明確です。
SELECT
category,
COUNT(*) AS order_count
FROM sales
WHERE category = 'book'
GROUP BY category;
SELECTに出す列とGROUP BYが合っていない
次のSQLは、カテゴリでまとめているのにamountをそのまま出そうとしているため、どの金額を表示するべきか曖昧です。
SELECT
category,
amount,
COUNT(*) AS order_count
FROM sales
GROUP BY category;
金額を出したいなら、例えば**SUM(amount)**のように集計します。
SELECT
category,
SUM(amount) AS total_amount,
COUNT(*) AS order_count
FROM sales
GROUP BY category;
GROUP BYだけで並び順が決まると思ってしまう
GROUP BYはグループを作るための句であり、表示順を決める目的ではありません。件数順や合計順で見たい場合は、ORDER BYを明示します。
SELECT
category,
COUNT(*) AS order_count
FROM sales
GROUP BY category
ORDER BY order_count DESC;
Q&A
Q1. HAVINGだけを書いて、GROUP BYを書かないことはありますか?
データベース製品やSQLの書き方によって扱いに差があります。初学者のうちは、集計結果を分類ごとに絞る場合はGROUP BYとHAVINGをセットで考えると安全です。
Q2. WHEREとHAVINGのどちらに置くべきか迷ったら?
その条件が、元の1行だけを見て判断できるならWHEREが候補です。COUNT、SUM、AVGなど、集計してからでないと判断できないならHAVINGが候補です。
Q3. HAVINGでSELECTの別名を使えますか?
使えるかどうかはデータベース製品によって差があります。迷う場合は、HAVING SUM(amount) >= 1000のように集計式を明示すると、製品差の影響を受けにくくなります。
要点まとめ
- GROUP BYは、同じ値を持つ行をグループにまとめるために使います。
- WHEREは集計前の行を絞り、HAVINGは集計後のグループを絞ります。
- 集計結果で条件を付けたいときは、HAVING COUNT(*) >= 2やHAVING SUM(amount) >= 1000のように書きます。
- SELECTに出す通常の列は、GROUP BYへ含めるか、集計関数で扱うのが基本です。
- 並び順が必要な場合は、ORDER BYを明示します。
公式資料・参考資料
- PostgreSQL 18 Documentation: SELECT
- SQLite Documentation: SELECT
- Microsoft Learn: GROUP BY (Transact-SQL)
- Microsoft Learn: HAVING (Transact-SQL)
※2026年7月14日に公式資料を確認して作成しています。利用しているデータベース製品によって、日付リテラル、別名参照、厳密な構文に違いがある場合があります。
内容に合うCTA
売上、問い合わせ、作業件数などの数字を見たいときは、いきなりSQLを書く前に、何でまとめるか、どの行を対象にするか、どの集計結果を残すかを分けて整理すると失敗しにくくなります。
MAO工房では、小規模事業者様のExcel集計、データベース集計、業務データの見直しを支援しています。集計条件が複雑になってきた場合は、お問い合わせからご相談ください。
MAO工房に相談できます
集計SQLと業務データ整理を相談できます
売上、問い合わせ、作業件数などの集計条件を整理し、Excelやデータベースから必要な数字を取り出すための設計を支援します。
- ✓ 集計したい単位を整理
- ✓ SQLやExcelの条件式を確認
- ✓ 小規模な業務データにも対応