HAVING: 集計結果を条件で絞る
Stage 2 — 第3章 | データ分析基礎カリキュラム 推定学習時間:30〜40分 | 難易度:★★★☆☆
この章で学ぶこと
前章では、GROUP BY を使ってカテゴリ別・顧客別に集計する方法を学びました。
集計表を作ると、次に「集計結果が一定以上のものだけ見たい」という場面が出てきます。
たとえば、ECサイトでは次のような問いがあります。
- 注文回数が3回以上の顧客だけを見たい
- 売上が10万円以上の商品カテゴリだけを抽出したい
- 平均注文金額が高い地域だけを確認したい
このように、集計した後の結果を絞るときに使うのが HAVING です。
この章を終えると、こんなことができるようになります:
WHEREとHAVINGの違いを説明できる- 集計後の件数や合計金額で結果を絞れる
GROUP BYとHAVINGを組み合わせたSQLを書ける- 実務で「注目すべきグループ」を抽出できる
1. WHEREは集計前、HAVINGは集計後
WHERE と HAVING はどちらも条件で絞るために使います。
ただし、絞るタイミングが違います。
| 句 | 絞る対象 | 例 |
|---|---|---|
WHERE |
集計前の行 | 完了注文だけに絞る |
HAVING |
集計後のグループ | 注文回数が3回以上の顧客だけに絞る |
顧客ごとの注文件数を出すSQLを考えます。
SELECT
customer_id,
COUNT(*) AS order_count
FROM orders
WHERE status = 'completed'
GROUP BY customer_id;
ここで WHERE status = 'completed' は、集計前に完了注文だけを残しています。
その後、customer_id ごとに集計します。
2. HAVINGで集計結果を絞る
完了注文が3回以上ある顧客だけを見たい場合は、HAVING を使います。
SELECT
customer_id,
COUNT(*) AS order_count
FROM orders
WHERE status = 'completed'
GROUP BY customer_id
HAVING COUNT(*) >= 3;
このSQLの流れは次の通りです。
ordersからデータを読むWHEREで完了注文だけに絞るGROUP BY customer_idで顧客ごとにまとめるHAVING COUNT(*) >= 3で注文回数3回以上の顧客だけ残す
HAVING は、COUNT(*) や SUM(...) のような集計結果に対する条件を書く場所です。
3. 売上が大きいカテゴリだけを見る
商品カテゴリ別の売上を出し、売上が10万円以上のカテゴリだけを残す例です。
SELECT
p.category,
SUM(oi.quantity * oi.unit_price) AS sales
FROM order_items AS oi
JOIN products AS p
ON oi.product_id = p.product_id
GROUP BY p.category
HAVING SUM(oi.quantity * oi.unit_price) >= 100000
ORDER BY sales DESC;
このSQLは、全カテゴリを集計したあと、売上が10万円以上のカテゴリだけを表示します。
実務では、すべてのカテゴリを並べるより、一定規模以上のカテゴリに絞ったほうが意思決定しやすいことがあります。 ただし、小さいカテゴリを見落としてよいかは、分析目的によって変わります。
4. 平均値で絞る
HAVING では、平均値も条件にできます。
SELECT
c.prefecture,
AVG(o.total_amount) AS average_order_amount,
COUNT(*) AS order_count
FROM orders AS o
JOIN customers AS c
ON o.customer_id = c.customer_id
WHERE o.status = 'completed'
GROUP BY c.prefecture
HAVING AVG(o.total_amount) >= 8000
ORDER BY average_order_amount DESC;
これは、完了注文の平均注文金額が8,000円以上の都道府県を抽出します。
平均値で絞るときは、件数も一緒に見るのが大切です。
注文が1件しかない地域の平均は、たまたま高く見えることがあります。
そのため、このSQLでは COUNT(*) AS order_count も表示しています。
5. 複数のHAVING条件を書く
集計後の条件を複数組み合わせることもできます。
SELECT
customer_id,
COUNT(*) AS order_count,
SUM(total_amount) AS total_sales
FROM orders
WHERE status = 'completed'
GROUP BY customer_id
HAVING COUNT(*) >= 3
AND SUM(total_amount) >= 30000
ORDER BY total_sales DESC;
これは、完了注文が3回以上あり、累計購入金額が3万円以上の顧客を抽出します。
このような条件は、優良顧客候補の抽出やキャンペーン対象者の選定に使えます。 ただし、条件の基準は業務目的に合わせて決める必要があります。
6. WHEREに集計関数は書かない
初学者がよく迷うのが、次のような書き方です。
SELECT
customer_id,
COUNT(*) AS order_count
FROM orders
WHERE COUNT(*) >= 3
GROUP BY customer_id;
これは適切ではありません。
WHERE は集計前の行を絞る句なので、COUNT(*) のような集計結果はまだ存在していないからです。
集計結果で絞る場合は、次のように HAVING を使います。
SELECT
customer_id,
COUNT(*) AS order_count
FROM orders
GROUP BY customer_id
HAVING COUNT(*) >= 3;
WHERE と HAVING の役割を分けて考えましょう。
7. HAVINGを使う前に全体も確認する
HAVING で条件を絞ると、注目したいグループだけを見られます。
一方で、条件に満たないグループが見えなくなります。
そのため、実務では次の順番で確認すると安全です。
- まず全カテゴリ・全顧客の集計表を見る
- 件数や売上の分布を確認する
- 目的に合う基準で
HAVINGを追加する - 除外されたグループが問題ないか確認する
SQLは結果を絞るほど見やすくなりますが、同時に見えない範囲も増えます。 条件を入れた理由を説明できることが大切です。
実務での使いどころ: 注目すべきグループだけを見る
HAVINGは、集計した後のグループを絞るために使います。 たとえば、全カテゴリを並べるだけでなく、売上が一定以上あるカテゴリだけを見たい場合に使います。
SELECT
p.category,
SUM(oi.quantity * oi.unit_price) AS sales
FROM order_items AS oi
JOIN products AS p
ON oi.product_id = p.product_id
GROUP BY p.category
HAVING SUM(oi.quantity * oi.unit_price) >= 100000
ORDER BY sales DESC;
このSQLは、売上が10万円以上のカテゴリだけを残します。 WHEREは行を絞り、HAVINGは集計後のグループを絞ります。 この違いを間違えると、分析対象が変わります。
| やりたいこと | 使う句 |
|---|---|
| 完了注文だけにする | WHERE |
| 2026年5月だけにする | WHERE |
| 売上10万円以上のカテゴリだけにする | HAVING |
| 注文件数10件以上の顧客だけにする | HAVING |
HAVINGは便利ですが、少数のグループだけを見ると全体感を失うことがあります。 HAVINGで絞る前の全体集計も確認しておきましょう。
ミニ演習
次の条件はWHEREとHAVINGのどちらに書くべきか考えてください。
status = 'completed'の注文だけにする。- カテゴリ別売上が100,000円以上のカテゴリだけにする。
- 2026年5月の注文だけにする。
- 注文件数が3件以上の顧客だけにする。
まとめ
| 構文 | 意味 | 例 |
|---|---|---|
WHERE |
集計前の行を絞る | WHERE status = 'completed' |
HAVING |
集計後のグループを絞る | HAVING COUNT(*) >= 3 |
HAVING SUM(...) |
合計値で絞る | HAVING SUM(total_amount) >= 100000 |
HAVING AVG(...) |
平均値で絞る | HAVING AVG(total_amount) >= 8000 |
この章のキーメッセージ:
HAVING は、集計した後の結果を条件で絞るための句です。WHERE は集計前、HAVING は集計後という違いを押さえましょう。
この章の確認
WHEREとHAVINGの違いを説明してください。- 完了注文が3回以上ある顧客を抽出するSQLを書いてください。
- カテゴリ別売上が10万円以上のカテゴリだけを表示するには、どの句を使いますか?
- 平均値で絞るとき、件数も一緒に確認したほうがよい理由を説明してください。