戦国IT - 情報処理技術者試験の過去問対策サイト
ブログお知らせお問い合わせ料金プラン

データベーススペシャリスト 2013年 午前205


問題文

社員表から、役割名がプログラマである社員が3人以上所属している部門の部門名を取得するSQL文はどれか。ここで、実線の下線は主キーを表す。
社員(社員番号、部門名、社員名、役割名)

選択肢

SELECT 部門名 FROM 社員
  GROUP BY 部門名
  HAVING COUNT(*) >= 3
  WHERE 役割名='プログラマ'
SELECT 部門名 FROM 社員
  WHERE COUNT(*) >= 3 AND 役割名='プログラマ'
  GROUP BY 部門名
SELECT 部門名 FROM 社員
  WHERE COUNT(*) >= 3
  GROUP BY 部門名
  HAVING 役割名 = 'プログラマ'
SELECT 部門名 FROM 社員
  WHERE 役割名='プログラマ'
  GROUP BY 部門名
  HAVING COUNT(*) >= 3
(正解)

🔒 解説は解答すると表示されます

GROUP BYとHAVING【午前2解説】

正解の理由

部門ごとに「役割名がプログラマである社員」を絞り、その数が3以上である部門名を出すためには、まず行レベルで役割を限定(WHERE)し、その限定後の行を部門ごとに集約(GROUP BY)して、集約結果に対して件数条件を課す(HAVING)必要があります。選択肢はこの手順どおりに記述されており、WHEREで役割名='プログラマ'を先に絞り、GROUP BY 部門名でグループ化した後、HAVING COUNT(*) >= 3で各グループの行数を評価しているため正解です。
(ポイント)
  • WHEREは行単位の絞り込み、HAVINGはグループ単位の絞り込み
  • 集約関数(COUNTなど)はWHEREでは使えないため、件数条件はHAVINGで評価する

解法ステップ

  1. 目的を明確にする:「部門ごとにプログラマの人数が3人以上」の部門名を取得する。
  2. プログラマである行だけを対象にする => WHERE 役割名 = 'プログラマ'
  3. 部門単位で集約する => GROUP BY 部門名
  4. 集約結果(各部門のプログラマ人数)に条件をつける => HAVING COUNT(*) >= 3
  5. SELECT で部門名を出力する
例(正しいSQLの一例):
SELECT 部門名
FROM 社員
WHERE 役割名 = 'プログラマ'
GROUP BY 部門名
HAVING COUNT(*) >= 3;

選択肢別の誤答解説

  • ア:
    • HAVING は GROUP BY の後に位置する句で、文法順序が誤っています(HAVING が先、WHERE が後になっている)。さらに、WHERE句でグループ単位の条件を指定できない点が問題です。WHERE は行フィルタ、HAVING はグループフィルタであることを混同しています。
  • イ:
    • WHERE句の中で COUNT(*) >= 3 のような集約関数を使っている点が誤りです。SQLでは集約関数による評価はグループ化後に行うため、集約条件は HAVING に書く必要があります。文の句順(WHERE の場所)は正しいものの、集約条件の書き場所が不適切です。
  • ウ:
    • 二重の誤りがあります。
      1. WHERE COUNT(*) >= 3 としており、WHERE句で集約関数を使っている点が誤りです(集約は HAVING で行う)。
      2. HAVING 役割名 = 'プログラマ' としている点も誤りです。HAVING で非集約列(役割名)を単独で条件にするには、その列が GROUP BY に含まれている必要があります。ここでは GROUP BY は部門名のみであり、役割名はグループ化列に含まれていないため、HAVING で役割名を直接比較するのは正しくありません(HAVING は原則として集約関数か、GROUP BY に含まれる列を条件にするため)。なお、HAVING を使う際に非集約列を参照できるかはDBMSによる差異もありますが、一般的な正しい書き方は「先にWHEREで役割名を絞る」ことです。
    • WHERE で役割名を先に限定し、GROUP BY 部門名 で部門ごとに集約し、HAVING で COUNT() >= 3 を判定しているため要件どおりです。COUNT() は行数を数えるので、社員番号が主キーであることから重複やNULLの影響を受けず期待どおりに動作します。

よくある誤解

  • HAVINGは必ずGROUP BYが必要である:
    • 一般的な使い方はGROUP BYと併用してグループごとの条件を指定することですが、標準SQLでは GROUP BY を省略した場合に全行を1つのグループとして扱い HAVING を使えるケースがあります(DBMSによって挙動の差があります)。ただし、本問のように「部門ごとに判定する」目的では GROUP BY が必須です。
  • WHEREで集約関数を使える:
    • WHEREは集約前の行フィルタなので、COUNT(*) のような集約関数は使えません。集約に基づく条件はHAVINGに書く必要があります。
  • HAVINGで非集約列を自由に参照できる:
    • HAVINGで非集約列を条件にするには、その列がGROUP BYに含まれているか、DBMSが拡張を許す場合のみです。標準的には、グループ化されていない列をHAVINGで単独参照するのは誤りです。

補足コラム

  • COUNT(*) と COUNT(列) の違い:
    • COUNT() は行数を数え、NULLも含めて行をカウントします(列にNULLがあっても行はカウントされる)。COUNT(役割名) は役割名がNULLでない行だけを数えます。本問では役割名で絞ってから集約しているため、COUNT() がシンプルで確実です。
  • パフォーマンス観点:
    • 可能ならWHEREで早めに行数を減らす(ここでは役割名で絞る)ことで、GROUP BY の負荷を下げられます。大規模データではインデックスの有無やDBMSの実行計画を確認するとよいです。

FAQ

Q1: HAVING を使うときに必ず GROUP BY が必要ですか?
A1: 通常はGROUP BYと併用してグループごとの条件を指定しますが、SQLではGROUP BYを省略すると全行を単一グループとして扱い HAVING を使える場合があります。ただしDBMSによる挙動差があるため、目的がグループ毎の判定なら明示的に GROUP BY を書くのが安全です。
Q2: COUNT() と COUNT(1) はどちらが速いですか?
A2: 多くのDBMSではほぼ同等で、最適化により同じ実行計画になります。可読性の観点で COUNT(
) を使うことが一般的です。
Q3: 非集約列を HAVING で条件にしてもよいのですか?
A3: 標準的には、HAVING 条件内で非集約列を参照する場合、その列は GROUP BY に含める必要があります。データベースによっては拡張を許して暗黙の動作をするものもありますが、移植性の観点から避けるべきです。

関連キーワード: SQL、GROUP BY、HAVING、WHERE、COUNT(*)、集約関数、句の順序、集計フィルタリング
← 前の問題へこの年度をクイズで解く次の問題へ →
戦国ITクイズ機能

\ せっかくなら /

データベーススペシャリスト
クイズ形式で学習しませんか?

クイズ画面へ遷移する

すぐに利用可能!

©︎2026 情報処理技術者試験対策アプリ

このサイトについてブログプライバシーポリシー利用規約特商法表記開発者について