join と in および exists 句の違いを説明する記事を読んでいましたが、NOT IN と NOT EXISTS 句を使用した場合の異なる結果の説明に混乱しました。NOT EXISTS 句と NOT IN 句の出力に違いがある理由を誰かが明確にすることはできますか? テーブル t2 から NULL 行 (t2.id = 8) を削除した後に試してみましたが、それでも同じ結果が得られました。
記事の SQL スクリプトは次のとおりです。
CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT)
GO
CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20))
GO
INSERT INTO t1
SELECT 1, 'title 1', 5 UNION ALL
SELECT 2, 'title 2', 5 UNION ALL
SELECT 3, 'title 3', 5 UNION ALL
SELECT 4, 'title 4', 5 UNION ALL
SELECT null, 'title 5', 5 UNION ALL
SELECT null, 'title 6', 5
INSERT INTO t2
SELECT 1, 1, 'data 1' UNION ALL
SELECT 2, 1, 'data 2' UNION ALL
SELECT 3, 2, 'data 3' UNION ALL
SELECT 4, 3, 'data 4' UNION ALL
SELECT 5, 3, 'data 5' UNION ALL
SELECT 6, 3, 'data 6' UNION ALL
SELECT 7, 4, 'data 7' UNION ALL
SELECT 8, null, 'data 8' UNION ALL
SELECT 9, 6, 'data 9' UNION ALL
SELECT 10, 6, 'data 10' UNION ALL
SELECT 11, 8, 'data 11'
SQL クエリとその説明は次のとおりです。
-- IN で正しい結果が得られません。-- これは、IN が NULL と 3 値ロジックを処理する方法によるものです -- NULL は不明として扱われるため、t2.t1id に null がある場合 -- NOT IN は NOT TRUE または NOT UNKNOWN を返します。そして、どちらも真ではありません。-- t2 テーブルの t1id 列に NULL がある場合、NOT IN クエリは常に空のセットを返します。
SELECT t1.*
FROM t1
WHERE t1.id NOT IN (SELECT t1id FROM t2)
-- NOT EXISTS は正しい結果を取得します
SELECT t1.*
FROM t1
WHERE NOT EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id)
GO
DROP TABLE t2
DROP TABLE t1
記事へのリンクは次のとおりです。 http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx
ありがとうございました!