【发布时间】:2023-03-28 05:41:02
【问题描述】:
我正在阅读一篇文章,解释了 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
谢谢!
【问题讨论】:
-
这里有一篇更好的文章:sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-join 除此之外,你还有什么问题?
-
@TimSchmelter “有人能解释一下为什么 NOT EXISTS 子句与 NOT IN 子句的输出之间存在差异吗?”
-
@Jocke:但他后来自己添加了一个解释,这很混乱。
-
他可能想确认他的解释是否属实。
-
我已经添加了文章中的解释。我不是很清楚这意味着什么。我正在寻找有关该解释的一些说明。