なぜ今、GROUP BYとHAVINGの理解が重要なのか
現場のデータベース運用において、単にデータを全件抽出するだけのSQLでは不十分です。「性別ごとの人数を知りたい」「売上が平均以上の店舗だけを抽出したい」といった、ビジネス上の意思決定に直結するクエリを作成する際、GROUP BY句とHAVING句は避けて通れない必須知識です。これらを正しく使い分けることで、アプリケーション側で複雑なループ処理を書く必要がなくなり、DBサーバー側で効率的に集計を完了させることができます。
基礎知識:WHEREとHAVINGの決定的な違い
集計を学ぶ上で最も重要なのが「処理の順番」です。
GROUP BY句は、指定したカラムの値が同じものを一つのグループにまとめます。
WHERE句は、グループ化される「前」に、個々の行に対して絞り込みを行います。
一方、HAVING句は、グループ化された「後」に、集計結果(合計や件数など)に対して絞り込みを行います。
よくある間違いとして「集計結果で絞り込みたいのにWHERE句を使ってしまいエラーになる」ケースがあります。「集計前はWHERE」「集計後はHAVING」と覚えておきましょう。
実装:グループ化と条件指定
まずは基本的なグループ化を行い、その結果から特定の条件に合致するものだけを抽出する手順を解説します。
サンプルプログラム:
以下は、ユーザーテーブルから「居住地ごとの人数」を集計し、さらに「2人以上住んでいる地域」だけを抽出する例です。
/ 1. 居住地ごとに人数を集計 /
SELECT address, COUNT() AS user_count
FROM user
GROUP BY address;
/ 2. 集計結果から、人数が2人以上の地域のみを絞り込む /
/ 集計関数であるCOUNTの結果に対して条件を課すため、HAVINGを使用します /
SELECT address, COUNT() AS user_count
FROM user
GROUP BY address
HAVING COUNT() >= 2;
/ 3. 【応用】WHEREとHAVINGの併用 /
/ まず東京以外に住んでいるユーザーに絞り込み、その後に地域でグループ化して集計 /
SELECT address, COUNT() AS user_count
FROM user
WHERE address != ‘Tokyo’
GROUP BY address
HAVING COUNT() >= 1;
応用・注意点:現場で陥りやすいバグと回避策
1. SELECT句に含めるカラムに注意
GROUP BY句で指定していないカラムをSELECT句に含めると、多くのSQLデータベースではエラーになります。グループ化のキーになっていない値は、集計関数(SUM, AVG, COUNTなど)を通さない限り特定できないためです。
2. パフォーマンスへの影響
グループ化を行うカラムにインデックスが貼られていない場合、大規模なデータセットでは処理が非常に重くなります。集計対象のカラムには、適切にインデックスを設計しておくことがDBAとしての腕の見せ所です。
3. NULLの扱い
GROUP BY句を使用する際、NULL値は「一つのグループ」として扱われます。もしNULLを除外したい場合は、グループ化する前にWHERE句で排除しておくのが鉄則です。
正しい集計SQLを書くことは、システム全体の負荷軽減にも繋がります。まずは手元の小さなテーブルから、HAVING句を活用して抽出条件を最適化する練習を始めてみてください。

コメント