
SQLのGROUP BYとHAVINGの違い|WHEREとの使い分けを例題で理解【基本情報・応用情報】
WHERE・GROUP BY・HAVINGを、結果表まで自力で確認
この記事では同じ売上データで、絞る行・まとめる単位・残るグループを比較します。まずSQLを読む→中間の表を紙に書く→最後の結果表を予想する、の順に進めてください。
条件を変えて演習したい方は、DB・SQL50問の無料見本5問で、問題の形式と解説をお試しください。無料記事で理解を整理したい方は、このまま本文だけでも学べます。50問教材を収録したセットを購入済みの方は、単品の追加購入は不要です。
「GROUP BYとHAVINGは何が違う?」「条件を書くならWHEREだけでいいのでは?」。SQLの集計問題で迷いやすい3つの句を、同じ売上データで比較します📚
この記事の軸は、WHEREは行を絞る、GROUP BYは行をまとめる、HAVINGはグループを絞るです。例題は学習用のオリジナルで、金額はすべてNULLではないものとします。
図で確認:集計前と集計後の違い

図のsales表には、A部門の1000円・2000円、B部門の800円・1200円という4行があります。このデータを使って、条件の位置による違いを見ていきます。
1.GROUP BYは「同じ値の行をまとめる」
部門ごとの売上合計を出したいときは、departmentでグループ化し、SUM(amount)で合計します。
SELECT department, SUM(amount) AS total
FROM sales
GROUP BY department;結果はA部門が3000、B部門が2000。元の4行が、部門ごとの2行にまとまります。
基本の集計問題では、SELECTに書く列がグループ化のキーか、SUMやCOUNTなどの集計結果かを確認しましょう。たとえばここでamountをそのまま選ぶと、A部門の1000と2000のどちらを表示するか定まりません。
2.HAVINGは「集計したグループを絞る」
例題①:部門別の売上合計が3000以上の部門だけを表示してください。
SELECT department, SUM(amount) AS total
FROM sales
GROUP BY department
HAVING SUM(amount) >= 3000;まず部門別に合計し、その合計値で絞ります。結果はA部門、3000の1行です。
この問題の条件は「1件の売上が3000以上」ではなく、「部門ごとの合計が3000以上」。そのためHAVINGに条件を書きます。
3.WHEREは「集計前の行を絞る」
例題②:1000円以上の売上だけを対象に、部門別の合計を表示してください。
SELECT department, SUM(amount) AS total
FROM sales
WHERE amount >= 1000
GROUP BY department;集計前に、B部門の800円の行を除きます。結果はA部門が3000、B部門が1200です。
HAVINGで集計後に部門を除くのと、WHEREで集計する材料の行を除くのでは、合計の対象が変わります。
4.WHEREとHAVINGは一緒に使える
例題③:1000円以上の売上だけを対象に集計し、その合計が3000以上の部門を表示してください。
SELECT department, SUM(amount) AS total
FROM sales
WHERE amount >= 1000
GROUP BY department
HAVING SUM(amount) >= 3000;考える順番は、①WHEREで800円の行を除く、②GROUP BYで部門ごとにまとめる、③HAVINGで合計3000以上のグループを残す、です。結果はA部門、3000になります。
これは結果を理解するための論理的な順番です。データベースが内部で実際に処理する順番は、最適化などによって変わることがあります。
5.よくある間違い
WHERE SUM(amount) >= 3000と書く
この形では、集計前のWHEREに同じ問い合わせの集計結果を置いています。グループの合計で絞るならHAVINGを使います。
GROUP BYだけで条件も指定できると思う
GROUP BYはグループ化の指定です。「合計3000以上」の絞り込みはHAVINGの役割です。
HAVING total >= 3000と書く
SELECTで付けた別名をHAVINGで使えるかは製品により異なります。この記事ではSUM(amount)を明記して、別名への依存を避けています。
6.確認問題:COUNTを使うなら?
元の4行について、売上件数が2件以上の部門を表示するSQLを考えてみてください。金額による条件はありません。
SELECT department, COUNT(*) AS sales_count
FROM sales
GROUP BY department
HAVING COUNT(*) >= 2;答えはA部門2件、B部門2件です。結果の行の並び順はORDER BYなしでは保証されません。
なお、HAVINGはGROUP BYなしでも使える場合があります。ここでは基本となる、部門別にグループ化する例に絞って説明しています。
7.SQLの問題演習を増やしたい方へ
IT資格攻略chでは、データベース・SQLを含む分野別問題集を公開しています。集計だけでなく、ほかのテーマも演習したい方は、無料の試し読みから確認してみてください。
👉 科目A実戦問題集【全8分野400問】〈有料・各記事に無料5問〉
次に集計問題を解くときは、条件が「元の1行」に対するものか、「まとめた結果」に対するものかを見分けてみましょう。
参考資料
PostgreSQL公式ドキュメント:Table Expressions
PostgreSQL公式ドキュメント:SELECT