メインコンテンツへスキップ
見出し画像

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

    あなたへのおすすめ