情報処理試験を勉強していると、「HAVING句って何?WHERE句と何が違うの?」と混乱しがちです。この記事では、HAVING句の定義・WHERE句との違い・SQLでの記述ルールを、日常の例え話と図解で整理します。
対象試験と出題頻度
HAVING句は、基本情報技術者・応用情報技術者で出題されるテーマです。
SQLのSELECT文に関する穴埋め問題や実行結果を選ぶ問題で、GROUP BY句とセットで問われるのが定番です。
詳細をクリックして確認
基本情報技術者
応用情報技術者
★★★★☆
ランクA(重要)必ず覚えておくべき
用語の定義
HAVING句とは、一言で言うと
「GROUP BYでグループ化した結果に対して、集約関数を使った条件で絞り込むためのSQL句」
のことです。
イメージとしては、「クラスごとの平均点を出した後に、”平均80点以上のクラスだけ表彰する”というフィルター」です。
テストの点数を生徒ごとに見て「80点以上の生徒だけ対象にする」のがWHERE句の役割。
一方、クラス単位で平均を出した後に「平均80点以上のクラスだけ残す」のがHAVING句の役割です。
HAVING句の基本情報
| 項目 | 内容 |
|---|---|
| 分類 | SELECT文を構成する句の1つ |
| 役割 | GROUP BYでまとめたグループに対して条件を指定し、条件を満たすグループだけを抽出する |
| 記述位置 | GROUP BYの直後、ORDER BYの前 |
| 条件に使えるもの | 集約関数(COUNT, SUM, AVG, MAX, MIN)またはGROUP BYに指定した列 |
解説
SELECT文には「WHERE → GROUP BY → HAVING → ORDER BY」という処理の流れがあります。
WHERE句で行を絞った後にGROUP BY句でグループ化し、その集計結果をさらにふるいにかけるのがHAVING句の仕事です。
WHERE句との決定的な違い
最も重要なのは「いつ絞り込むか」の違いです。ここだけは確実に押さえてください。
| 比較項目 | WHERE句 | HAVING句 |
|---|---|---|
| 絞り込み対象 | 個々の行(レコード) | グループ化後のグループ |
| 実行タイミング | GROUP BYの前 | GROUP BYの後 |
| 集約関数の使用 | 使用不可 | 使用可(AVG, COUNT等) |
WHERE句に「AVG(点数) >= 80」のような集約関数を書くと構文エラーになります。
集約関数による条件は必ずHAVING句に書くというのが鉄則です。
図解:SELECT文の処理順序とHAVING句の位置
DBMSがSELECT文を処理する順番を図で確認します。HAVING句は4番目に処理されます。
SELECT文の実行順序 ― DBMSは上から順に処理する
| ① | FROM | どの表からデータを取るか決める |
| ▼ | ||
| ② | WHERE | 条件に合わない行を除外する |
| ▼ | ||
| ③ | GROUP BY | 指定列の値が同じ行をまとめる |
| ▼ | ||
| ④ | HAVING | 条件に合わないグループを除外する ← ここが本記事のテーマ |
| ▼ | ||
| ⑤ | SELECT | 必要な列を取り出す・集計する |
| ▼ | ||
| ⑥ | ORDER BY | 結果を並べ替える |
コードではSELECTを最初に書くが、DBMSの処理はFROMから始まる。この違いが穴埋め問題で狙われる。
具体例:得点テーブルでの動作
以下の「得点」テーブルを使って、HAVING句の動作を確認します。
得点テーブル
| 学生番号 | 科目 | 点数 |
|---|---|---|
| S001 | 数学 | 90 |
| S001 | 英語 | 70 |
| S002 | 数学 | 85 |
| S002 | 英語 | 80 |
| S003 | 数学 | 60 |
| S003 | 英語 | 65 |
「学生ごとの全科目平均が80点以上の学生」を抽出するSQL文は次のようになります。
SELECT 学生番号, AVG(点数) AS 平均点 FROM 得点 GROUP BY 学生番号 HAVING AVG(点数) >= 80
このSQL文の処理を順番に追うと、次のようになります。
処理の流れ
STEP 1:FROM 得点テーブル全6行を取得
STEP 2:GROUP BY 学生番号 学生ごとに3グループに分割
S001グループ(90, 70)→ 平均80 / S002グループ(85, 80)→ 平均82.5 / S003グループ(60, 65)→ 平均62.5
STEP 3:HAVING AVG(点数) >= 80 平均80以上のグループだけ残す
S001(平均80)→ 残る / S002(平均82.5)→ 残る / S003(平均62.5)→ 除外
STEP 4:SELECT 結果を出力
| 学生番号 | 平均点 |
|---|---|
| S001 | 80 |
| S002 | 82.5 |
詳細解説:WHEREで代用できないケースを確認する
仮に上のSQL文のHAVINGをWHEREに置き換えて次のように書いたとします。
SELECT 学生番号, AVG(点数) AS 平均点 FROM 得点 WHERE AVG(点数) >= 80 -- ← 構文エラー! GROUP BY 学生番号
WHEREは行単位で動作するため、集約関数(AVG, COUNT等)を条件に指定できません。DBMSはWHEREの処理時点ではまだグループ化を行っていないので、「平均」という概念が存在しないためです。
さらに、構文の記述順として「GROUP BYの後にWHEREを書く」こと自体が文法違反になります。正しい記述順はWHERE → GROUP BY → HAVINGです。
では、この構文が試験でどのように出題されるか見ていきましょう。
HAVING句の核心を3行で
・GROUP BY後のグループに対して集約関数で条件を絞る句
・WHERE句は行単位(グループ化前)、HAVING句はグループ単位(グループ化後)
・集約関数を条件に使えるのはHAVINGだけ。WHERE句に書くと構文エラー
試験ではこう出る!
HAVING句はFE・APの午前(科目A)問題で、GROUP BY句とのセット出題が定番化しています。出題パターンは大きく2つです。
過去問での出題実績
| 試験回 | 出題内容 | 問われたポイント |
|---|---|---|
| FE R1秋 午前 問26 |
「得点」表から学生ごとの平均点が80点以上の学生を抽出するSQL文の空欄補充 | ・GROUP BY 学生番号 + HAVING AVG(点数) >= 80 が正解 ・「GROUP BY 科目」や「WHERE 点数 >= 80」がひっかけ |
| AP H31春 午前 問28 |
「試験結果」表から2018年度の平均点数が600点以上のクラスを取得するSQL文を選択 | ・WHERE句で年度を絞った後にGROUP BY + HAVINGで集計条件を指定する順序 ・HAVINGに集約関数でない列を書いた選択肢が構文エラーになる点 |
| FE H28春 午後 問3 |
遊園地の入園情報を管理する関係データベースで、GROUP BY → HAVINGを含むSQL文の空欄補充 | ・午後問題でもGROUP BY+HAVING構文は頻出 ・会員番号と会員名でグループ化後に抽出条件を指定する流れ |
IPA試験での出題パターン
パターン1:「SQL文の空欄を埋めよ」(最頻出)
テーブル定義と目的(「○○ごとの平均が△△以上のものを取得」)が示され、GROUP BY句の対象列とHAVING句の条件式を組み合わせた正しい選択肢を選ぶ形式。ひっかけとして「GROUP BYの後にWHEREを書いた選択肢(構文エラー)」や「GROUP BYの列を間違えた選択肢」が混ぜられる。
パターン2:「正しい結果を選べ」
テーブルのデータとSQL文が提示され、HAVING句による絞り込み後の結果表を選ぶ形式。手を動かして各グループの集計値を計算し、条件に合うグループだけを残す作業が必要になる。
試験ではここまででOKです。HAVING句に指定できる条件の詳細なルール(GROUP BY列か集約関数のみ)まで覚えておけば、選択肢を消去法で絞れます。
【確認テスト】理解度チェック
ここまでの内容を理解できたか、簡単なクイズで確認してみましょう。
Q. 「売上」表に対して次のSQL文を実行したとき、HAVING句の役割として最も適切な説明はどれか。
SELECT 商品名, SUM(金額) AS 合計金額 FROM 売上 WHERE 売上日 BETWEEN '2024-01-01' AND '2024-12-31' GROUP BY 商品名 HAVING SUM(金額) >= 100000
- A. 売上日が2024年の行だけを個別に抽出し、金額が10万円以上の行を返す。
- B. 売上表の全行を商品名ごとにグループ化した後、商品名を昇順で並べ替える。
- C. 商品名ごとにグループ化した後、合計金額が10万円以上のグループだけを抽出する。
正解と解説を見る
正解:C
解説:
HAVING句は、GROUP BYでグループ化された後のグループに対して集約関数による条件を適用する句です。このSQL文では、商品名ごとにグループ化した上で、SUM(金額)が10万円以上のグループだけを結果として返します。
選択肢Aは、WHERE句の役割を述べています。WHERE句が「2024年の行を抽出」する部分を担っていますが、「金額が10万円以上の行」という表現は個々の行に対する条件であり、HAVING句が行うグループ単位の集計条件とは異なります。選択肢Bは、ORDER BY句の機能(並べ替え)を混同しています。HAVING句にソート機能はありません。
よくある質問(FAQ)
Q. HAVING句はGROUP BY句なしで使えますか?
SQL標準の規格上はGROUP BYなしでHAVINGを書くことも文法違反ではありません。その場合、テーブル全体が1つのグループとして扱われます。ただし、実務でもIPA試験でもGROUP BYとセットで使うのが通常です。GROUP BYなしのHAVING句が出題された実績はないため、「HAVING句はGROUP BYの後に書くもの」と覚えておけば十分です。
Q. HAVING句にGROUP BYで指定していない列は書けますか?
書けません。HAVING句に指定できるのは、GROUP BY句で指定した列か、集約関数(COUNT, SUM, AVG, MAX, MIN)のいずれかです。AP H31春 午前問28では、HAVING句にグループ化されていない「点数」列を直接指定した選択肢が構文エラーとして不正解になっています。この制約を知っていれば、選択肢の消去に使えます。
Q. WHERE句とHAVING句の両方に条件を書くケースはありますか?
あります。実際にAP H31春 午前問28がまさにそのパターンです。「WHERE句で2018年度の行に絞る → GROUP BYでクラスごとにまとめる → HAVINGで平均600点以上のクラスだけ残す」という流れで、両方の句がそれぞれ別の役割で条件を指定しています。WHERE句で先に不要な行を除外し、HAVING句で集計後の条件を適用するのが正しい組み合わせです。
Q. 実務ではHAVING句はどんな場面で使いますか?
売上データの分析が代表例です。「月ごとの売上合計が100万円以上の月だけ抽出したい」「顧客ごとの注文回数が5回以上のリピーターだけ一覧にしたい」といった、集計結果に基づくフィルタリングが必要な場面で使います。BIツールやレポート生成の裏側でも、GROUP BY + HAVINGのSQL文が自動生成されていることが多いです。