SQL 中有没有办法将 EXCEPT 语句重写为 NOT IN 语句?

Is there a way to rewrite EXCEPT statements into NOT IN statements in SQL?

我已经学习了几周 SQL,并且刚刚完成了关于使用 IN 和 NOT IN 的家庭作业问题。我设法得到了正确的答案,但是,我使用了 EXCEPT 子句,我们还没有真正允许使用它。据我所知,EXCEPT 和 NOT IN 在 SQL 中是非常相似的语句,但我不明白有什么区别。这是我查询的一般格式:

SELECT *
FROM table
WHERE x IN (
    SELECT x
    /* ... some subquery*/
    EXCEPT
    SELECT x
    /* ... some other subquery*/ 
)

有没有办法不使用 EXCEPT 语句来重写这个通用查询? EXCEPT 和 NOT IN 通常有何不同?

编辑:This other post 似乎有一些很好的信息,但它似乎专注于 EXISTS 而不是 IN,它们有不同的目的不是吗?

这可能有助于您理解 Except 和 NOT IN 之间的区别

EXCEPT 运算符 returns 来自左侧 table 的所有不同行,这些行在右侧 table.

中不存在

另一方面,"NOT IN" 将 return 左侧 table 右侧 table 中不存在的所有行,但不会删除从结果中复制行。

SQL 是一种声明性语言。因此,有许多结构可以转化为相同的关系代数树/执行计划。例如,您可以使用 INNER JOIN 或 CROSS JOIN + WHERE 或 , + WHERE 或 LEFT/RIGHT JOIN + WHERE.

指定内部联接

EXCEPT/INTERSECT 是集合运算符,而 IN/NOTIN 是谓词。考虑你的例子,

SELECT *
FROM table
WHERE x IN (
    SELECT x
    /* ... some subquery*/
    EXCEPT
    SELECT x
    /* ... some other subquery*/ 
)

这可以用 IN / NOT IN 写成:

SELECT *
FROM table as t1
WHERE t1.x IN (
    SELECT t2.x
    FROM t2
    WHERE t2.x NOT IN (
                      SELECT t3.x
                      FROM t3
    )
)

现在,就语法而言,它们的意思相同,但在语义上它们可能不会产生相同的结果。例如,如果列 X 可以为空,则 NOT IN 将产生不同的结果。

最后,对于简单的情况,如果您在 SQL Server Management Studio 中查看这两个查询的执行计划,您会发现它们使用相似的计划/连接策略。这是因为 SQL 服务器会将语法转换为经过优化以生成执行计划的关系树。翻译完成后,不同查询的最终计划可能相同。