ホーム > データベーススペシャリスト試験 > 2011年
データベーススペシャリスト試験 2011年 午前2 問05
“社員番号” と “氏名” を列としてもつR表とS表に対して, 差 (R-S) を求めるSQL 文はどれか。ここで, R 表とS 表の主キーは“社員番号”であり, “氏名”は“社員番号”に関数従属する。
ア:
SELECT R.社員番号, S.氏名 FROM R, S
WHERE R. 社員番号 <> S. 社員番号
イ:
SELECT 社員番号, 氏名 FROM R
UNION SELECT 社員番号, 氏名 FROM S
ウ:
SELECT 社員番号, 氏名 FROM R
WHERE NOT EXISTS (SELECT FROM S
WHERE R. 社員番号 = S. 社員番号)
(正解)エ:
SELECT 社員番号, 氏名 FROM S
WHERE S.社員番号 NOT IN (SELECT 社員番号 FROM R
WHERE R.社員番号= S.社員番号)
解説
解説:R表とS表の差集合 (R - S) を求めるSQL文について
問題の内容整理
-
R表 と S表 はそれぞれ、
- 列: 社員番号 と 氏名 を持つ
- 主キーは 社員番号
- 氏名 は 社員番号 に関数従属(すなわち社員番号が一意に氏名を決定)
-
求めたいのは、R表に存在するがS表には存在しないレコードの集合(差集合 R - S)
SQLで差集合を表現する方法
-
差集合 (R - S) とは、
「Rに含まれているが、Sには含まれていない」レコードを選ぶこと。 -
主キーが社員番号であるため、差集合の判定は社員番号を基準に行うのが適切。
選択肢の検証
ア:
SELECT R.社員番号, S.氏名 FROM R, S
WHERE R.社員番号 <> S.社員番号
-
効率的に差集合を求める意図とは異なる。
-
条件は「Rの社員番号とSの社員番号が異なる組のすべての組み合わせ」を選択しており、
Rにしかない行を正確に抽出できない。 -
【誤り】
イ:
SELECT 社員番号, 氏名 FROM R
UNION SELECT 社員番号, 氏名 FROM S
-
これは 和集合 のSQL文。
-
RとSのすべての社員を重複なく取得。
-
差集合ではない。
-
【誤り】
ウ:
SELECT 社員番号, 氏名 FROM R
WHERE NOT EXISTS (SELECT FROM S
WHERE R.社員番号 = S.社員番号)
-
Rの中で、Sに同じ社員番号が存在しないものを取得。
-
主キーの社員番号を基準に比較しているため、氏名の不整合等は考慮不要。
-
正しくR-S(差集合)を表現している。
-
【正解】
エ:
SELECT 社員番号, 氏名 FROM S
WHERE S.社員番号 NOT IN (SELECT 社員番号 FROM R
WHERE R.社員番号 = S.社員番号)
-
Sから差集合を求めている(S - R)。
-
質問はR - Sなので逆方向。
-
【誤り】
まとめ
-
差集合 R - S は、
R に存在し、S には存在しない社員を主キー(社員番号)で判定して抽出すること。 -
選択肢ウのSQL文は、
WHERE NOT EXISTS
とサブクエリを使用し、Rの社員番号がSに存在しない場合のみ抽出している。
この文が正解となる。
追加説明:NOT EXISTS
と NOT IN
の違い
-
NOT EXISTS
はサブクエリの存在チェックに適し、NULLによる副作用の影響を受けにくい。 -
一方、
NOT IN
はサブクエリにNULLがあると動作が変わりやすいので注意が必要。 -
この問題では主キー(社員番号)はNULLにならない前提なので動作上大きな差はないが、一般的に差集合には
NOT EXISTS
が安全で推奨される。
以上の理由により、正解はウ となります。