これは理解するために、そしてよく出る過去問題として、とぉ~ってもよい問題だったので頑張って平打ちすることにしました。(テストに丸々でるかもよぉ~!)
Customer_CSystem
Customer_HSystem
『You need to display customers who appear in both tables and have a non-null CustomerCode.』
A.
SELECT c.CustomerCode, c.CustomerName, h.CustomerCode, h.CustomerName
FROM Customer_CSystem c
INNER JOIN Customer_HSystem h
ON c.CustomerCode = h.CustomerCode AND c.CustomerName = h.CustomerName
両方のテーブルからマッチしている値を返すけど、もし重複しているものがあれば、それも全部返す。
B.
SELECT CustomerCode, CustomerName
FROM Customer_CSystem
INTERSECT
SELECT CustomerCOde, CustomerName
SROM Customer_HSystem
INNER JOINと同じだけど、『DISTINCT』を返します。だから、重複分はないよ。
C.
SELECT c.CustomerCode, c.CustomerName
FROM Customer_CSystem c
LEFT OUTER JOIN Customer_HSystem h
ON c.CUstomerCode = h.CustomerCode
WHERE h.CustomerCode IS NULL AND c.CustomerCode IS NOT NULL
ベーステーブルが左で(FROMのテーブル)、LEFT JOINされたテーブルはマッチしない場合に『NULL』と表示される。ここで大事なのは、ベーステーブルのすべての行が返ってきます。
D.
SELECT CustomerCode, CustomerName
FROM Customer_CSystem
EXCEPT
SELECT CustomerCode, CustomerName
『INTERSECT』と同じく『DISTINCT』を返します。だから、重複分はありません。しかし、『マッチしない』値が返ってきます。
E.
SELECT CustomerCOde, CustomerName
FROM Customer_CSystem
UNION
SELECT CustomerCode, CustomerName
FROM Customer_HSystem
そこかこのサイトで「UNIONは問合せの行をお互いに後に置くが、JOINはデカルト積を生成し、それを部分集合化する。まったく別の操作である。」と書いてあります。ようは、全てのマッチングを計算した後で『WHERE』でフィルターにかけるのがJOINだとしたら、UNIONだと二つ以上のテーブルを結合させてやることで、単体のテーブルとして結果を返します。そして、UNIONだけなら、重複データは返しません。
F.
SELECT CustomerCode, CustomerName
FROM Customer_CSystem
UNION ALL
SELECT CustomerCode, CustomerName
FROM Customer_HSystem
重複データをかえします。
G.
SELECT c.CustomerCOde, c.CustomerName, h.CustomerCode, h.CustomerName
FROM Customer_CSystem c
CROSS JOIN Customer_HSystem
これだけ、『ON』を使った条件は指定しません。これはもう、天文学的な数字になっちゃう可能性のある『すべてのマッチングパターン』です。『WHERE』文がない場合は十中八九ひっかけ問題でしょうね。
H.
SELECT c.CustomerCode, c.CustomerName, h.CustomerCode, h.CustomerName
FROM Customer_CSystem c
FULL OUTER JOIN Customer_HSystem h
ON c.CustomerCode = h.CustomerCode AND c.CustomerName = h.CustomerName
ベーステーブルと右テーブルのマッチする値全部とマッチしない値全部を返します。
はい、いつものように読み解きましょう。
『You need to display customers who appear in both tables』
ふむふむ、両方のテーブルにある『customers』を表示させればいいのか。
『and have a non-null CustomerCode』
それじゃ、『LEFT JOIN』以外のマッチングだな。『INNER JOIN』かな?『UNION』かな?それとも『INTERSECT』?
では、『A. INNER JOIN』はどうだろう。
『DISTINCT』がないから、重複データがとれちゃう。ぶっぶーっ!
では、『B. INTERSECT』はどうだろう。
『DISTINCT』なくても『INTERSECT』は勝手に重複データをはぶいてくれるよね。これかな?
では、『E. UNION』はどうだろう。
ううぉ~っ。。。悩む。だけど、フィルターないから、『NULL』データもユニークデータとしてでてきちゃうよね、きっと。だから違うかな?
- INTERSECT just compares 2 sets and picks only distinct equivalent values from both sets. It's important to note that NULL marks are considered as equals in INTERSECT set operator. Also sets should contain equal number of columns with implicitly convertible types.
2.JOIN 両方のテーブルにNULLがある場合、SQLではNULL <> NULLであるため、それらの行は返されません。
- If there are NULL marks in both tables those rows will not be returned because NULL <> NULL in SQL.




そしてこのCustomerIDをフィルターしていないということで、ここにも大きな落とし穴があった。
しかし、知らぬが仏。どのステートメントにもこのフィルターはないから、出力結果に関係なし!
ただし、上記の「『DISTINCT』がないから、重複データがあるから無理」ってのは当てはまりませんでした。
もっとしっかりテーブルの値全部見なければなりませんね。
SELECT c.CustomerCode, c.CustomerName, h.CustomerCode, h.CustomerName
FROM Customer_CSystem c
INNER JOIN Customer_HSystem h
ON c.CustomerCode = h.CustomerCode AND c.CustomerName = h.CustomerName