gpt4 book ai didi

sql - 将 NOT IN 转换为 NOT EXISTS

转载 作者:行者123 更新时间:2023-12-03 09:47:15 24 4
gpt4 key购买 nike

有一段时间了解 NOT EXISTS 的用法,主要是如何转换我的 NOT IN 解决方案,以便我能够真正了解我是如何实现结果的。
在 askTom、oracle 论坛和 stackoverflow 上有几篇文章,但找不到任何可以明确帮助理解此问题的内容。如果我通过我的菜鸟搜索错过了它,我深表歉意。

SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND S.S_Id NOT IN(SELECT e.S_Id
FROM ENROLLMENT e
WHERE e.Mark < 70);

内容方面的一些帮助,试图找到在她们注册的任何类(class)中从未获得低于 70 分的女学生。

最佳答案

当你掌握它的窍门时,这相当简单:

SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND S.S_Id NOT IN(SELECT e.S_Id -- take this line
FROM ENROLLMENT e
WHERE e.Mark < 70);

那条线基本上比较 S.S_Id与所有 e.S_Id来自子查询的值。

现在将其更改为 NOT EXISTS并进行相等检查 S.S_Id = e.S_Id , 在子查询中:
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT e.S_Id
FROM ENROLLMENT e
WHERE (e.Mark < 70) -- if this is complex, you'll need parentheses
AND S.S_Id = e.S_Id);

较小的可能变化是意识到 (SELECT e.S_Id ...真的不需要 e.S_Id .带有 EXISTS 的子查询和 NOT EXISTS只需检查是否有返回的行,列值无关紧要。你可以把 SELECT *或那里的常量( SELECT 1 很常见)或 SELECT NULL甚至 SELECT 1/0 (是的,那行得通!):
SELECT s.S_Fname, s.S_Lname
FROM STUDENT s
WHERE s.S_Sex = 'F'
AND NOT EXISTS (SELECT 1
FROM ENROLLMENT e
WHERE e.Mark < 70
AND S.S_Id = e.S_Id);

另一个主要考虑因素是,当您以这种方式进行转换时,(看似等效) NOT EXISTSNOT IN仅当 S_Id 时,查询的写作才真正等效列不可为空。如果 e.S_Id列可以为空, NOT IN可能导致整个查询根本不返回任何行(因为 x NOT IN (a, b, c, ...) 等价于 x<>a AND x<>b AND ... 并且当 a,b,c... 之一是 NULL 时,该条件不成立。)

出于类似的原因,如果 s.S_Id,您将得到不同的结果。可以为空(在这种情况下不太可能,因为它可能是主键,但在其他情况下很重要。)

所以最好使用 NOT EXISTS ,因为即使任一列可以为空,它的行为也会有所不同( S.S_Id = e.S_Id 检查将丢弃较早为空的行),并且通常这种行为是想要的。问题中有很多细节: NOT IN vs NOT EXISTS ,在@Martin Smith 的回答中。您还可以找到转换 NOT IN 的方法。至 NOT EXISTS并保持与空相关(令人不快)的行为。

关于sql - 将 NOT IN 转换为 NOT EXISTS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16707229/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com