T-SQL:比较两个表 - 第二个表中不存在的记录

Posted

技术标签:

【中文标题】T-SQL:比较两个表 - 第二个表中不存在的记录【英文标题】:T-SQL: Comparing Two Tables - Records that don't exist in second table 【发布时间】:2008-12-16 18:00:29 【问题描述】:

如果UNION ALL 是T-SQL 中的添加。减法的等价物是什么?

例如,如果我有一个表 PEOPLE 和一个表 EMPLOYEES。而且我知道如果我从PEOPLE 中删除EMPLOYEES 记录,我将留在我的公司CONTRACTORS

有没有类似于UNION ALL 的方法?一个我不必指定任何字段名称的地方?我问的原因是这只是一个假设的例子。我需要对许多不同的表多次执行此操作。假设EMPLOYEESPEOPLE的schema是一样的。

【问题讨论】:

【参考方案1】:

您可以使用EXCEPT operator 从另一组中减去一组。这是使用 EMPLOYEES 和 PEOPLE 临时表的代码示例。据我所知,您需要将字段名称与 EXCEPT 运算符一起使用。

CREATE TABLE #PEOPLE
(ID INTEGER,
 Name NVARCHAR(50))

CREATE TABLE #EMPLOYEE
(ID INTEGER,
 Name NVARCHAR(50))
GO

INSERT #PEOPLE VALUES (1, 'Bob')
INSERT #PEOPLE VALUES (2, 'Steve')
INSERT #PEOPLE VALUES (3, 'Jim')
INSERT #EMPLOYEE VALUES (1, 'Bob')
GO

SELECT ID, Name
FROM #PEOPLE
EXCEPT 
SELECT ID, Name
FROM #EMPLOYEE
GO

最终查询将返回 PEOPLE 表中不存在于 EMPLOYEE 表中的两行。

【讨论】:

请记住,EXCEPT 只会为您提供 DISTINCT 值。在您的情况下,如果您添加另一个 id =2 的史蒂夫,那么无论如何您只会得到其中一个。当然,ID 可能是主键。【参考方案2】:

不要使用 UNION,而是使用 EXCEPT,(或 INTERSECT 只获取两者中的记录) 如

中所述

msdn EXCEPT Link for Sql2k8

msdn EXCEPT Link for Sql2k5

【讨论】:

【参考方案3】:
SELECT
     P.*
FROM
     People P
LEFT OUTER JOIN Employees E ON
     E.ID = P.ID     -- Or whatever your PK-FK relationship is
WHERE
     E.ID IS NULL

对于 SQL Server,这可能是您能做到的最高效的方式。

【讨论】:

两个人认为返回正确答案的解决方案值得否决,而无需解释原因。他们何时会实施该功能以要求对否决发表评论? :) 左外连接返回左表中的所有记录,无论是否在第二个表中找到匹配项。当您只想从第一个表中获取第二个表中不存在的那些记录时,不能使用它。 :) 这就是 WHERE 子句包含“E.ID IS NULL”的原因。在宣布有问题之前,您可能应该了解它并进行理想的测试。 我同意你的观点,你的解决方案在 SQL Server 中更快。请阅读这篇文章sqlservercentral.com/Forums/Topic541726-338-1.aspx 这是一个很好的解决方案,但是,在最近做一些性能分析时,我遇到了这样的情况,这样做不一定是最好的选择。据我所知,原因是如果连接会导致大量连接记录,SQL 必须执行连接才能执行 IS NULL 测试。在这些情况下,在 where 子句中使用子查询会快得多,例如 WHERE NOT EXISTS(Select 1 from Employees e where e.id = p.id)。这很大程度上取决于两个表的相对大小。【参考方案4】:
SELECT * FROM Table1
WHERE Table1.Key NOT IN (SELECT Table2.Key FROM Table2 WHERE Table2.Key IS NOT NULL)

添加了 IS NOT NULL 以使人们开心。

我同意汤姆的观点。他的版本很可能更有效。使用我的唯一可能的原因可能是它更漂亮。

【讨论】:

“Table2.Key”中的空值失败。 添加 IS NOT NULL 然后,如果您期望 NULL,但我假设 Table2.Key 是 PK 并且没有 NULL【参考方案5】:

很遗憾,您的设计存在问题。 而不是有两个表 PEOPLE 和 CONTRACTOR。 您应该有一个表 PEOPLE 和另一个表 TYPE(如果某些人可以担任多个角色,则可能需要另一个表)。 在您的 PEOPLE 表中,您可以参考 TYPE 表。

那么你的要求就变成了

SELECT * from PEOPLE, TYPE
WHERE PEOPLE.type_id = TYPE.id 
AND TYPE.name = 'CONTRACTOR'

SELECT * from PEOPLE, TYPE
WHERE PEOPLE.type_id = TYPE.id 
AND TYPE.name = 'EMPLOYEE'

(未经测试)

【讨论】:

这只是一个例子。同意这个设计很糟糕。【参考方案6】:

当我比较表以查找不在另一个中的数据时,我通常使用 SQL 分区。

select *(or selected matching field) 
from tableA as A
where not exist
(select *(or selected matching field) 
from tableB as B 
where A.key = B.key)

此查询将返回tableA中没有经过除法处理的结果。

select *(or selected matching field) 
from tableA as A
where exist
(select *(or selected matching field) 
from tableB as B 
where A.key = B.key)

此查询将返回两个表中匹配的所有数据行,因此如果 tableA 中的行数据不在 tableB 中,则不会检索该行数据。

【讨论】:

【参考方案7】:

我发现使用 SQLMerger 之类的工具为您执行此操作要容易得多。结果以更好的方式显示,之后您可以轻松地继续处理您需要对数据执行的任何操作。

www.auisoft.com/SQLMerger

比较两个表的示例:http://auisoft.com/SQLMerger/How-to/visualize-differences-in-2-databases/

【讨论】:

以上是关于T-SQL:比较两个表 - 第二个表中不存在的记录的主要内容,如果未能解决你的问题,请参考以下文章

删除第二个表中不包含的记录

索引视图中完全外连接的替代方案

HQL 左外连接用于查找一个表中存在而其他表中不存在的记录

SQL计算第二个表中一个表中单词的出现次数

SQL 视图:将初始表与分析表进行比较以返回初始表中不存在的值

比较两个表的 xml [PENTAHO]