超電磁砲でデータベース(Union編)

今回はテーブルの結合の項目で触れられることが多い概念 UNION, INTERSECT, EXCEPT を扱う。LEVEL が 0 の人物、所属が アイテム の人物を調べてみよう。
SELECT NAME FROM STATUS WHERE LEVEL = 0 ;
SELECT NAME FROM AFF WHERE TEAM = ‘アイテム’ ;
結果を図にすると次のようになる。

LEVEL = 0 の集合と TEAM = ‘アイテム’ の集合の組み合わせが何通りか考えられる。

LEVEL = 0 OR TEAM = ‘アイテム’UNION, UNION ALL (両方に現れるものを重複表示)
共通部分LEVEL = 0 AND TEAM = ‘アイテム’INTERSECT
LEVEL = 0 AND TEAM <> ‘アイテム’EXCEPT

これらは2つの結果が同じ NAME だけからなる集合だから成り立つ。NATURAL JOIN と同じような使い方をするが、適用対象は同じタイプに限られる。普通の問い合わせでもできそうな気がするが、今回は異なるテーブルから抽出した集合に対する操作なのでそれほど単純ではなさそうだ。

出題をするが、動作確認をしたところ ( ) の付け方によりエラーが生じることがあった。これは仕様なのかそれとも文法の誤りなのか確認できていない。(1) でエラーが生じたら解答例を見てから以下の課題を解いてみると良い。

課題
(1) LEVEL = 0 または TEAM = ‘アイテム’ に該当する人物を検索せよ。
(2) (1) で両方に該当する人物は重複して表示せよ。
(3) LEVEL = 0 かつ TEAM = ‘アイテム’ に該当する人物を検索せよ。
(4) LEVEL = 0 かつ TEAM <> ‘アイテム’ に該当する人物を検索せよ。
(5) LEVEL <> 0 かつ TEAM = ‘アイテム’ に該当する人物を検索せよ。

解答例 (ORDER BY NAME は結果を比較しやすいようにつけただけで不要である)

(1) SELECT * FROM ( SELECT NAME FROM STATUS WHERE LEVEL = 0 UNION SELECT NAME FROM AFF WHERE TEAM = ‘アイテム’ ) ORDER BY NAME ;

(2) SELECT * FROM ( SELECT NAME FROM STATUS WHERE LEVEL = 0 UNION ALL SELECT NAME FROM AFF WHERE TEAM = ‘アイテム’ ) ORDER BY NAME ;

(3) SELECT * FROM ( SELECT NAME FROM STATUS WHERE LEVEL = 0 INTERSECT SELECT NAME FROM AFF WHERE TEAM = ‘アイテム’ ) ORDER BY NAME ;

(4) SELECT * FROM ( SELECT NAME FROM STATUS WHERE LEVEL = 0 EXCEPT SELECT NAME FROM AFF WHERE TEAM = ‘アイテム’ ) ORDER BY NAME ;

(5) SELECT * FROM ( SELECT NAME FROM AFF WHERE TEAM = ‘アイテム’ EXCEPT SELECT NAME FROM STATUS WHERE LEVEL = 0 ) ORDER BY NAME ;