使用EXCEPT where 1=0

4
我看到有人发布了一种基本的去重条目方法,但没有解释它是如何工作的。我知道它可以运行,但我想知道它的工作原理和评估过程。接下来我将贴出代码和我的想法。我希望有人告诉我,我的思考过程是否正确,如果不正确,请有人为我解释一下。
CREATE TABLE #DuplicateRcordTable (Col1 INT, Col2 INT)
INSERT INTO #DuplicateRcordTable
SELECT 1, 1
UNION ALL
SELECT 1, 1
UNION ALL
SELECT 1, 1
UNION ALL
SELECT 1, 2
UNION ALL
SELECT 1, 2 
UNION ALL
SELECT 1, 3
UNION ALL
SELECT 1, 4
GO

这将返回一个基本表格:

Table1

然后使用以下代码来排除重复项:

SELECT col1,col2
FROM #DuplicateRcordTable
EXCEPT
SELECT col1,col2
FROM #DuplicateRcordTable WHERE 1=0

我的理解是1=0创建了一个“临时”表,结构相同但没有数据。

那么这段代码是否开始向新的空表添加数据呢?

例如,它是否查看第一对Col1、Col2对1,1并说“我在表中没有找到它”,因此将其添加到“temp”表和最终结果,然后检查下一行,也是1,1,然后看到它已经在“temp”表中,所以它不会被添加到最终结果中...以此类推。


按组分组是另一种方法(除了Gordon的DISTINCT方法更清晰之外)https://sqlperformance.com/2017/01/t-sql-queries/surprises-assumptions-group-by-distinct - S3S
2个回答

4

EXCEPT是一种去除重复项的集合操作。也就是说,它从第一个表中取出不在第二个表中的所有内容,然后进行去重操作。

如果第二个集合为空,则只剩下去重操作。

因此,

SELECT col1, col2
FROM #DuplicateRcordTable
EXCEPT
SELECT col1, col2
FROM #DuplicateRcordTable
WHERE 1 = 0;

等同于:

SELECT DISTINCT col1, col2
FROM #DuplicateRcordTable

这是编写查询的更典型方式。

这也等同于:

SELECT col1,col2
FROM #DuplicateRcordTable
UNION
SELECT col1,col2
FROM #DuplicateRcordTable
WHERE 1 = 0;

但这并不能解释 1 = 0 是如何生效的? - Dale K
1
@DaleBurrell . . . 1 = 0 会从第二个查询中删除所有行,因此结果为空集。 - Gordon Linoff
@GordonLinoff 有必要在同一张表上使用 Except 函数吗?我知道它在不同的表中如何工作,但如果你可以只使用 distinct,那么为什么要在同一张表上使用它呢?另外,为什么需要 WHERE 1=0?谢谢! - Nick A
1
如果您使用DISTINCT,那就没有@NickA了。否则,您必须采取一些措施来返回一个空的结果集(如果您使用except),比如选择null,null或使用1=0的方法...或者您可以删除WHERE子句,但这会更慢。这两种方法都是实现DISTINCT的歧义方式。另一种方法是我在主要评论中发布的GROUP BY。 - S3S
@NickA……我不知道你的问题是什么。在同一张表上使用except可能会有用,但如果你的意图是去除重复项,那么没有理由使用except。为此,有更简单的语法。 - Gordon Linoff

1
这种方法有效的原因在于 EXCEPT 的定义,根据 MS 文档所述:

EXCEPT 返回左侧输入查询中不被右侧输入查询输出的不同行。

关键词在于 distinct。将 where 1 = 0 放入第二个查询会使其返回零结果,但 EXCEPT 运算符本身会将左侧查询的行数减少到那些是 distinct 的行。

如 @Gordon Linoff 在他的回答中所说,有一种更简单直接的方法来完成此操作。

事实上,示例中使用相同的表格在左右查询中可能会让人产生误解。只要右侧查询中的值不存在于左侧查询中,以下查询将完成相同的操作:

SELECT col1, col2
FROM @DuplicateRecordTable
EXCEPT
SELECT -1, -1

参考资料: https://learn.microsoft.com/zh-cn/sql/t-sql/language-elements/set-operators-except-and-intersect-transact-sql?view=sql-server-2017


我觉得你的回答和戈登的有所不同,但我可能漏掉了一些细节。由于今天是一年中的最后一天,我的头脑可能没有平时那么清晰。 - S3S
@scsimon - OP 特别关心为什么使用 1=0 子句,我觉得这个问题在 Gordon 的回答中有些模糊。这个问题不是要找到去重的方法,而是要理解这种方法为什么有效。 - Dale K
啊,好的。我以为他的第二和第三句话是为了那个而说的,但更多的解释从来没有伤害过。 - S3S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接