基本情報技術者 2010年 春期 午前(科目A) 問31
問題文
“商品”表、“在庫”表に対する次のSQL文と、同じ結果が得られるSQL文はどれか。ここで、下線部は主キーを表す。
SELECT 商品番号 FROM 商品
WHERE 商品番号 NOT IN (SELECT 商品番号 FROM 在庫)

選択肢
ア:SELECT 商品番号 FROM 在庫
WHERE EXISTS (SELECT 商品番号 FROM 商品)
イ:SELECT 商品番号 FROM 在庫
WHERE NOT EXISTS (SELECT 商品番号 FROM 商品)
ウ:SELECT 商品番号 FROM 商品
WHERE EXISTS (SELECT 商品番号 FROM 在庫
WHERE 商品.商品番号 = 在庫.商品番号)
エ:SELECT 商品番号 FROM 商品
WHERE NOT EXISTS (SELECT 商品番号 FROM 在庫
WHERE 商品.商品番号 = 在庫.商品番号)(正解)
🔒 解説は解答すると表示されます
NOT INとNOT EXISTSの同値性【午前解説】
正解の理由
正解は エ です。元のSQLは「商品表の各商品番号について、在庫表に同じ商品番号が存在しないものを選ぶ」意味です。エのSQLは商品表の各行に対して在庫表を相関(WHERE 商品.商品番号 = 在庫.商品番号)して存在チェックし、存在しなければ出力するため論理的に同値です。相関サブクエリを使ったNOT EXISTSはNULLの影響を受けないため、元の意図を安全に表現します。
解法ステップ
- 元SQLの意味を日本語で言い換える:「商品表にあるが在庫表にはない商品番号を取得」
- サブクエリの役割を確認する:在庫表の全商品番号を抽出して商品表の値と比較している点を把握。
- 同等な表現を検討する:各商品ごとに在庫表を参照して存在しなければ出力する、つまり相関NOT EXISTSが対応。
- 選択肢を照合:テーブル(商品/在庫)の対象、存在チェックの有無・否定、相関条件の有無を確認して一致するものを選ぶ。
- NULLの有無を意識:NOT IN をそのまま使うとサブクエリにNULLがある場合誤動作する可能性があるため注意。
選択肢別の誤答解説
- ア: SELECT 商品番号 FROM 在庫 WHERE EXISTS (SELECT 商品番号 FROM 商品)
- 在庫表から選んでおり、かつサブクエリは商品表が空でない限り常に真なので目的と無関係です。テーブルが逆です。
- イ: SELECT 商品番号 FROM 在庫 WHERE NOT EXISTS (SELECT 商品番号 FROM 商品)
- これも在庫表から取得しており、NOT EXISTSのサブクエリは商品表が空か否かだけを参照するため用途と異なります。
- ウ: SELECT 商品番号 FROM 商品 WHERE EXISTS (SELECT 商品番号 FROM 在庫 WHERE 商品.商品番号 = 在庫.商品番号)
- 相関はあるが EXISTS のため「在庫に存在する商品」を返し、元の「在庫に存在しない商品」とは逆になります。
- エ: SELECT 商品番号 FROM 商品 WHERE NOT EXISTS (SELECT 商品番号 FROM 在庫 WHERE 商品.商品番号 = 在庫.商品番号)
- 各商品について在庫に該当がなければ出力する、元SQLと論理的に一致するため正解です。
よくある誤解
- NOT IN と NOT EXISTS は常に同じ振る舞いをすると思い込む誤解。サブクエリがNULLを返すとNOT INは結果を失敗させる点で異なります。
- サブクエリに相関が不要だと考える誤り。相関がないとテーブル間の比較が行われず、意図した行選択になりません。
- テーブル名の見間違い(商品/在庫)で逆のテーブルから取得してしまう単純ミスが多いです。
補足コラム
- NOT IN と NOT EXISTS の違い(NULLの影響)
- 例:在庫テーブルに商品番号 NULL が含まれると、
WHERE 商品番号 NOT IN ( ... , NULL, ... )は通常どの値も FALSE/UNKNOWN 扱いとなり結果が空になる可能性があります。NOT EXISTS は行の有無を論理的に判定するためこの問題を回避します。
- 例:在庫テーブルに商品番号 NULL が含まれると、
- LEFT JOIN を使う代替表現(実務でよく使う)
SELECT P.商品番号 FROM 商品 P LEFT JOIN 在庫 S ON P.商品番号 = S.商品番号 WHERE S.商品番号 IS NULL;- LEFT JOIN + IS NULL も「存在しない」を表す一般的な書き方で、実行計画によってはパフォーマンス上有利なことがあります。
FAQ
Q1: NOT IN と NOT EXISTS はどちらを使うべきですか?
A1: サブクエリがNULLを返す可能性がある場合はNOT EXISTSが安全です。NULLが完全に排除されていることが保証されるならNOT INでも可ですが、実務ではNOT EXISTSやLEFT JOIN IS NULLを推奨します。
A1: サブクエリがNULLを返す可能性がある場合はNOT EXISTSが安全です。NULLが完全に排除されていることが保証されるならNOT INでも可ですが、実務ではNOT EXISTSやLEFT JOIN IS NULLを推奨します。
Q2: パフォーマンス差はありますか?
A2: DBエンジンやインデックス、データ分布によって異なります。一般にNOT EXISTSやLEFT JOINの方が最適化がしやすいことが多いので、実行計画を確認してください。
A2: DBエンジンやインデックス、データ分布によって異なります。一般にNOT EXISTSやLEFT JOINの方が最適化がしやすいことが多いので、実行計画を確認してください。
Q3: 相関サブクエリが遅い場合の対処は?
A3: 適切なインデックスを張る、JOIN に変換して実行計画を確認する、統計情報を最新にする等で改善を図ります。
A3: 適切なインデックスを張る、JOIN に変換して実行計画を確認する、統計情報を最新にする等で改善を図ります。
関連キーワード: SQL、NOT IN、NOT EXISTS、相関サブクエリ、NULL、LEFT JOIN、外部結合、差集合、集合演算、データ整合性

\ せっかくなら /
基本情報技術者を
クイズ形式で学習しませんか?
クイズ画面へ遷移する→
すぐに利用可能!

