我正在阅读一篇文章,解释了 join 和 in 和存在子句之间的区别,但我对使用 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 和三值逻辑 -- 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
谢谢!