【2026年7月】SQL「HAVING句」とWHEREの違いを図解!GROUP BY・集計関数との組み合わせ方まで徹底解説
この記事の内容
「SQLのHAVING句とWHEREはどう違うの?」「GROUP BYと組み合わせる順番がわからない」——SQLを学習中の方がよくつまずくポイントです。結論から言うと、WHEREは「行のフィルタリング(集計前)」に使い、HAVINGは「グループ化した結果のフィルタリング(集計後)」に使うのが基本の違いです。
この記事では、HAVING句の基本・GROUP BYとの組み合わせ・WHEREとの3つの違い・実践的な使い分けパターン・よくあるエラーの解決法・Claude Codeを使ったSQL業務の効率化まで図解と実例で徹底解説します。
01 HAVING BASICS SQL「HAVING句」とは?基本と役割 GROUP BYで集計した結果に条件をかけるためのSQL構文
📚 用語解説
HAVING句(HAVING Clause):SQLにおいて、GROUP BY句でグループ化・集計した結果に対して絞り込み条件を指定する構文。集計関数(COUNT・SUM・AVG・MAX・MIN等)を条件に使えるのが特徴。WHERE句が「行単位のフィルタリング」なのに対し、HAVING句は「グループ単位のフィルタリング」を担当します。GROUP BY なしでも使えますが、実用上はほぼ必ずGROUP BYとセットで登場します。
HAVINGの基本構文はこのようになります:
SELECT 列名, 集計関数(列名)
FROM テーブル名
[WHERE 行フィルタ条件] -- 省略可
GROUP BY グループ化する列名
HAVING グループ集計後の条件;
具体例を見てみましょう。「各部署の社員数が5人以上の部署だけを取得する」クエリです:
-- employeesテーブル(社員テーブル)から
-- 部署(department)ごとに社員数(COUNT)を集計して
-- 5人以上の部署だけ抽出する
SELECT department, COUNT(*) AS emp_count
FROM employees
GROUP BY department
HAVING COUNT(*) >= 5;
上記のクエリの実行結果例:
| department(部署) | emp_count(社員数) |
|---|---|
| 営業部 | 12 |
| システム部 | 8 |
| 人事部 | 6 |
社員数が4人以下の部署(例:法務部3人・総務部2人)は結果に表示されません。
02 GROUP BY + HAVING GROUP BY と HAVING の組み合わせ SQLの実行順序を理解すればHAVINGの使い方が自然にわかる
📚 用語解説
GROUP BY句(GROUP BY Clause):SQLで指定した列の値が同じ行をひとまとめ(グループ)にする構文。グループ化することで、グループごとの合計・平均・件数などを集計関数で計算できるようになります。例えば「departmentでGROUP BY」すると、同じ部署の社員が1つのグループにまとまり、各グループの平均給与・最大給与・人数などを計算できます。
SQLが実行されるときの順序はSELECT文に書く順序とは異なります。実際の実行順序を理解することがHAVING句の理解につながります:
テーブルを特定
行フィルタ(集計前)
グループ化・集計
グループフィルタ(集計後)
表示列を選択
並び替え
WHEREはGROUP BYより先に実行されるため、この時点ではまだ集計が終わっていません。したがって「WHERE COUNT(*) >= 5」と書いてもCOUNT(*)の結果がまだ存在しないのでエラーになります。集計後の条件はHAVINGに書く——これが基本ルールです。
GROUP BY + HAVING の実践的なパターンをいくつか見てみましょう:
-- パターン1: 売上合計が100万円以上のカテゴリを取得
SELECT category, SUM(sales) AS total_sales
FROM orders
GROUP BY category
HAVING SUM(sales) >= 1000000;
-- パターン2: 平均スコアが80以上の生徒クラスを取得
SELECT class_id, AVG(score) AS avg_score
FROM exam_results
GROUP BY class_id
HAVING AVG(score) >= 80;
-- パターン3: 2回以上購入した顧客を抽出(リピーター分析)
SELECT customer_id, COUNT(*) AS purchase_count
FROM orders
GROUP BY customer_id
HAVING COUNT(*) >= 2;
03 WHERE BASICS SQL「WHERE句」とは?基本と役割 テーブルの行を絞り込む最も基本的なフィルタリング構文
📚 用語解説
WHERE句(WHERE Clause):SQLで指定した条件に合う行だけを取得するフィルタリング構文。= / != / > / < / >= / <= / BETWEEN / IN / LIKE / IS NULL などの条件演算子が使えます。GROUP BY・HAVING・ORDER BYより前に実行されるため、テーブル全体のデータを集計する前に絞り込む「事前フィルタ」の役割を担います。集計関数(COUNT・SUM等)はWHEREには使えません。
WHERE句の基本構文と使用例:
-- 基本構文
SELECT 列名
FROM テーブル名
WHERE 条件式;
-- 例1: 2024年以降の注文のみ取得
SELECT * FROM orders
WHERE order_date >= '2024-01-01';
-- 例2: 特定の部署かつ給与が50万円以上の社員
SELECT name, department, salary
FROM employees
WHERE department = '営業部' AND salary >= 500000;
-- 例3: 商品名に「限定」が含まれるものを検索
SELECT * FROM products
WHERE product_name LIKE '%限定%';
04 WHERE vs HAVING WHERE と HAVING の3つの違い タイミング・集計関数の使用可否・パフォーマンスの3点で明確に区別される
| 比較項目 | WHERE句 | HAVING句 |
|---|---|---|
| フィルタのタイミング | GROUP BY の前(集計前) | GROUP BY の後(集計後) |
| 集計関数の使用 | 使えない(エラーになる) | 使える(COUNT・SUM・AVG等) |
| GROUP BY との関係 | 関係なく使える(必須でない) | 通常GROUP BYとセットで使う |
| 対象 | 個々の行(1行ごと) | グループ全体(まとまり) |
| 実行順序 | ②番目 | ④番目 |
| パフォーマンス | 絞り込みが早い(集計前に行数を減らす) | 集計後に絞るので処理量多め |
最も重要な違いをもう一度整理します:
全行が対象
集計前にフィルタ
グループ化
集計関数実行
グループが対象
集計後にフィルタ
「WHERE COUNT(*) > 5」のように書くとエラー("Invalid use of group function")になります。集計関数を条件に使いたいときは必ずHAVINGに書いてください。反対に「HAVING 列名 = 値」のように集計関数なしでもHAVINGに書くことは文法上可能ですが、パフォーマンスを考えるとWHEREに書くべきです。
WHERE と HAVING を同時に使う場合
WHEREとHAVINGは同じSELECT文に両方書けます。用途を分けて使い分けることが重要です:
-- 「2024年の注文」に絞ったうえで(WHERE)
-- 「購入回数が3回以上の顧客」を抽出する(HAVING)
SELECT customer_id, COUNT(*) AS purchase_count
FROM orders
WHERE order_date >= '2024-01-01' -- 集計前フィルタ(行の絞り込み)
GROUP BY customer_id
HAVING COUNT(*) >= 3; -- 集計後フィルタ(グループの絞り込み)
05 PRACTICAL PATTERNS 実践!WHERE・HAVING の使い分けと応用パターン ビジネス分析でよく使うSQLパターンを実例で習得する
📚 用語解説
集計関数(Aggregate Functions):SQLでグループ内の複数行のデータをまとめて1つの値に変換する関数の総称。主な集計関数:COUNT(*)=行数・SUM(列名)=合計値・AVG(列名)=平均値・MAX(列名)=最大値・MIN(列名)=最小値。WHERE句には使えず、SELECT句かHAVING句に書く必要があります。NULLを含む行は COUNT(列名) では無視されますが COUNT(*) では数えられます(違いに注意)。
パターン集:実務でよく使う10パターン
-- [1] リピーター分析: 3回以上購入した顧客
SELECT customer_id, COUNT(*) AS orders
FROM orders GROUP BY customer_id HAVING COUNT(*) >= 3;
-- [2] 売上ランキング: 月次売上上位カテゴリ
SELECT category, SUM(amount) AS monthly_sales
FROM sales WHERE month = '2024-06'
GROUP BY category HAVING SUM(amount) > 500000
ORDER BY monthly_sales DESC;
-- [3] 在庫アラート: 残数が10個以下の商品
SELECT product_id, SUM(stock) AS total_stock
FROM inventory GROUP BY product_id HAVING SUM(stock) <= 10;
-- [4] アクティブユーザー: 今月3回以上ログインしたユーザー
SELECT user_id, COUNT(*) AS login_count
FROM access_logs
WHERE login_date >= '2024-06-01'
GROUP BY user_id HAVING COUNT(*) >= 3;
-- [5] 重複レコード検出: 同じメールが2件以上あるもの
SELECT email, COUNT(*) AS dup_count
FROM users GROUP BY email HAVING COUNT(*) >= 2;
-- [6] 平均単価の高いカテゴリ(平均1万円超)
SELECT category, AVG(price) AS avg_price
FROM products GROUP BY category HAVING AVG(price) > 10000;
-- [7] 返品率の高い商品(返品数が総注文数の10%超)
SELECT product_id,
SUM(CASE WHEN status='returned' THEN 1 ELSE 0 END) AS returns,
COUNT(*) AS total_orders
FROM orders GROUP BY product_id
HAVING SUM(CASE WHEN status='returned' THEN 1 ELSE 0 END) > COUNT(*) * 0.1;
-- [8] 部署の最高給与が100万円超
SELECT department, MAX(salary) AS max_salary
FROM employees GROUP BY department HAVING MAX(salary) > 1000000;
-- [9] 1ヶ月あたりの平均注文件数が50件以上の顧客
SELECT customer_id, COUNT(*)/12 AS monthly_avg
FROM orders WHERE YEAR(order_date)=2023
GROUP BY customer_id HAVING COUNT(*)/12 >= 50;
-- [10] 評価が4.0以上のショップのみ(レビュー数10件以上の条件付き)
SELECT shop_id, AVG(rating) AS avg_rating, COUNT(*) AS review_count
FROM reviews GROUP BY shop_id
HAVING COUNT(*) >= 10 AND AVG(rating) >= 4.0;
06 ERRORS & FIXES よくあるエラーと解決法 HAVING・GROUP BY・集計関数に関するよくあるエラーパターンと対処法
📚 用語解説
Invalid use of group function(グループ関数の無効な使用):WHEREにCOUNT()やSUM()などの集計関数を使ったときに発生するMySQLのエラー。例:WHERE COUNT(*) > 5 → エラー。原因は「WHEREはGROUP BYより前に実行されるため、この時点では集計関数の結果が存在しない」ため。解決方法は集計関数を使った条件をHAVINGに移すこと。
| エラー・問題 | 原因 | 解決法 |
|---|---|---|
| WHERE COUNT(*) > 5 がエラー | WHERE句に集計関数は使えない | HAVING COUNT(*) > 5 に変更 |
| GROUP BY後の列が一致しない | SELECT句の非集計列がGROUP BYに含まれていない | GROUP BYにすべての非集計列を追加 |
| HAVINGだけでWHEREを使っていない(遅い) | 集計前に絞り込めるのにしていない | 日付等の条件はWHEREに移動(パフォーマンス改善) |
| COUNT(列名) が想定より少ない | NULLを含む行がCOUNT(列名)でカウントされない | COUNT(*) を使う、またはNULLを別途確認 |
| HAVING ORDER BY で順番が変わらない | ORDER BYをHAVINGの後に書いていない | ORDER BYはHAVINGより後に書く(実行順通り) |
-- よくある間違い(エラー)
SELECT department, COUNT(*)
FROM employees
WHERE COUNT(*) >= 5 -- エラー!WHEREに集計関数は使えない
GROUP BY department;
-- 正しい書き方
SELECT department, COUNT(*)
FROM employees
GROUP BY department
HAVING COUNT(*) >= 5; -- 集計後の条件はHAVINGに書く
07 CLAUDE CODE 【独自】Claude CodeでSQL業務を効率化する方法 SQLを学習するにも・実務で使うにも、Claude Codeを活用すれば圧倒的に速くなる
SQLはマーケター・営業担当・経営企画など、非エンジニア職でもデータ分析のために必要になるスキルです。しかし「GROUP BY・HAVING・JOIN・サブクエリ」と学ぶことが多く、独学で習得するには時間がかかります。Claude Codeを使えば、SQLの学習速度と実務での生産性を大幅に上げられます。
# Claude Codeへの依頼例(こんな感じで日本語で頼める)
"""
以下の条件でSQLを書いてください:
- テーブル: orders(customer_id, product_id, amount, order_date, status)
- 2024年の注文に限定
- ステータスが'completed'の注文のみ
- 顧客ごとに合計購入金額を集計
- 合計購入金額が50,000円以上の顧客だけ取得
- 購入金額の多い順に並べる
"""
# Claude Codeが生成するSQL(例)
SELECT
customer_id,
SUM(amount) AS total_amount,
COUNT(*) AS order_count
FROM orders
WHERE
order_date >= '2024-01-01'
AND order_date < '2025-01-01'
AND status = 'completed'
GROUP BY customer_id
HAVING SUM(amount) >= 50000
ORDER BY total_amount DESC;
Claude CodeでSQLを使う場合のおすすめフロー:
日本語で書く
SQLを生成
実行確認
修正依頼(あれば)
実行
08 SUMMARY まとめ|HAVING句 vs WHERE句の使い分けを完全マスター 実行タイミングの違いを頭に入れれば、迷わず使い分けられる
📚 用語解説
サブクエリ(Subquery):別のSELECT文の中に書くSELECT文のこと。FROM句・WHERE句・SELECT句の中に書ける。HAVINGで対応できない複雑な集計条件を書くときに使う場合がある。例:「平均売上が全体平均の2倍以上のカテゴリ」はHAVINGとサブクエリの組み合わせで実現できます。
SQL活用・データ分析のAI化を相談したい方へ
「社内のデータをSQLで分析したいがクエリが書けない」「GA4・Salesforce・MA等のデータをAIで自動集計・レポート化したい」——弊社GENAIでは、Claude Codeを活用したデータ分析自動化・SQL業務効率化の支援を提供しています。
NEXT STEP
この記事の内容を、あなたのビジネスで
実践してみませんか?
AI活用を自社で回せるようになりたい方へ
AI鬼管理
Claude Code・Cowork導入支援から業務設計・社内浸透まで実践ベースで伴走。「自社で回せる組織」を90日で作る経営者向けトレーニング。
よくある質問
Q. HAVING句はWHERE句と同じ列名を使ってもいいですか?
A. はい、可能です。「WHERE status = 'active'」でactiveな行に絞りつつ、「HAVING COUNT(*) >= 5」でその中から5件以上のグループを取得するという組み合わせが典型的なパターンです。ただし同じ列への条件をHAVINGとWHEREの両方に書く場合は、集計関数なしの条件はWHERE(パフォーマンス上)、集計後の条件はHAVINGに書き分けてください。
Q. HAVINGをGROUP BYなしで使えますか?
A. 文法上は使えますが、実用的にはほぼGROUP BYとセットで使います。GROUP BYなしのHAVINGは、テーブル全体を1つのグループとして扱い、例えば「HAVING COUNT(*) > 100」はテーブル全体の行数が100より多いかどうかを確認するだけになります。
Q. MySQL・PostgreSQL・SQLiteでHAVINGの挙動は違いますか?
A. HAVINGの基本的な使い方はSQLの標準規格に従っているため、MySQL・PostgreSQL・SQLite・SQL Serverなどの主要DBMSで同様に動作します。ただし細かい集計関数の仕様やNULLの扱いに差があるため、移行時は確認が必要です。
Q. HAVING句で複数の条件を指定できますか?
A. はい。AND/OR演算子で複数の条件を組み合わせられます。例:「HAVING COUNT(*) >= 10 AND AVG(score) >= 80」で「10件以上かつ平均80点以上のグループ」を取得できます。
Q. HAVINGとサブクエリはどちらを使うべきですか?
A. 「集計した結果に直接条件をつける」場合はHAVINGの方がシンプルです。サブクエリは「他のテーブルの集計結果と比較する」「HAVINGではネストが深くなりすぎる」場合に使います。基本はHAVINGを試して、対応できない場合にサブクエリを検討してください。
Q. Claude CodeでSQLを学ぶのに最適な使い方は?
A. 「このSQLの各行が何をしているか説明して」と貼り付けると、一行ずつ解説してもらえます。「このSQLをもっとシンプルに書き直して」「実行が遅い、最適化して」などの依頼も有効です。また「こんな集計をしたい」と日本語で伝えて生成されたSQLを読み解くことで、実務に直結した学習ができます。
Q. HAVING句はORDER BY と一緒に使えますか?
A. はい、使えます。ORDER BYは必ずHAVINGの後に書きます。「HAVING COUNT(*) >= 5 ORDER BY COUNT(*) DESC」のように書くと、5件以上のグループを件数の多い順に並べて取得できます。
Claude Codeで業務自動化を90日で叩き込む
経営者向けの伴走型パーソナルトレーニング
Claude Code を業務に落とし込む
専門研修コース一覧
受講者本人の業務を題材に、「使いこなせる」状態になるまで伴走する研修プログラム。1対1特化型・ハンズオン・法人講座の3コースを展開中。業務特化・実装まで踏み込むタイプのClaude Code研修です。
研修コース一覧を見る →AI鬼管理へのお問い合わせ
この記事を読んで気になった方へ。
AI鬼管理の専門スタッフが、御社に最適な
業務自動化プランを無料でご提案します。




