在sql中查找两个表之间的重复差异

时间:2014-10-06 14:00:58

标签: sql sql-server tsql sql-server-2012

我尝试在两个表之间找到重复的行。此代码仅在记录不重复时有效:

(select [Name], [Age] from PeopleA
except
select [Name], [Age] from PeopleB)
union all
(select [Name], [Age] from PeopleB
except
select [Name], [Age] from PeopleA)

如何查找丢失的重复记录。 Robert 34表中的PersonA,例如:

人物

Name   | Age
-------------
John   | 45
Robert | 34
Adam   | 26
Robert | 34

PersonB

Name   | Age
-------------
John   | 45
Robert | 34
Adam   | 26

3 个答案:

答案 0 :(得分:5)

您可以使用UNION ALL来连接两个表,使用Group ByHaving子句来查找重复项:

SELECT x.Name, x.Age, Cnt = Count(*) 
FROM (   
    SELECT a.Name, a.Age
    FROM PersonA a

    UNION ALL

    SELECT b.Name, b.Age
    FROM PersonB b  
) x
GROUP BY x.Name, x.Age
HAVING COUNT(*) > 1

根据您在评论中的说明,您可以使用以下查询来查找PersonA中与PersonB不同的所有名称 - 年龄组合:

WITH A AS(
   SELECT a.Name, a.Age, cnt = count(*)
   FROM PersonA a
   GROUP BY a.Name, a.Age
),
B AS(
   SELECT b.Name, b.Age, cnt = count(*)
   FROM PersonB b
   GROUP BY b.Name, b.Age
)
SELECT a.Name, a.Age
FROM A a LEFT OUTER JOIN B b
  ON a.Name = b.Name AND a.Age = b.Age
WHERE a.cnt <> ISNULL(b.cnt, 0)

Demo


如果你还想找到PersonB但不在PersonA中的人,你应该使用FULL OUTER JOIN,正如Gordon Linoff所评论的那样:

WITH A AS(
   SELECT a.Name, a.Age, cnt = count(*)
   FROM PersonA a
   GROUP BY a.Name, a.Age
),
B AS(
   SELECT b.Name, b.Age, cnt = count(*)
   FROM PersonB b
   GROUP BY b.Name, b.Age
)
SELECT Name = ISNULL(a.Name, b.Name), Age = ISNULL(a.Age, b.Age)
FROM A a FULL OUTER JOIN B b
  ON a.Name = b.Name AND a.Age = b.Age
WHERE ISNULL(a.cnt, 0) <> ISNULL(b.cnt, 0)

Demo

答案 1 :(得分:1)

我喜欢蒂姆的答案,但如果缺少记录,你需要检查两个表格。他只检查表A中是否缺少记录。请尝试检查其中任何一个表中是否缺少记录以及记录次数。

Select *, 'PersonB' MissingInTable, a.cnt - isnull(b.cnt,0) TimesMissing From 
(
Select *, count(1) cnt from PersonA group by Name, Age) A Left join 
(Select *, count(1) cnt from PersonB group by Name, Age) B
On a.age=b.age and a.name=b.name
where a.cnt>isnull(b.cnt,0)

Union All

Select *, 'PersonA' MissingInTable, b.cnt - isnull(a.cnt,0) TimesMissing From 
(
Select *, count(1) cnt from PersonA group by Name, Age) A Right join 
(Select *, count(1) cnt from PersonB group by Name, Age) B
On a.age=b.age and a.name=b.name
where b.cnt>isnull(a.cnt,0)

在此处查看演示:http://sqlfiddle.com/#!6/06020/13

答案 2 :(得分:0)

添加另一个UNION ALL

代码:

(SELECT [Name], [Age], 'Missing from B' AS [Type] from PeopleA
EXCEPT
SELECT [Name], [Age], 'Missing from B' AS [Type] from PeopleB)
UNION ALL
(SELECT [Name], [Age], 'Missing from A' as [Type] from PeopleB
EXCEPT
SELECT [Name], [Age], 'Missing from A' AS [Type] from PeopleA)
UNION ALL
SELECT [Name], [Age], 'Duplicate' AS [Type] FROM PeopleA INNER JOIN PeopleB ON PeopleA.Name = PeopleB.Name AND  
PeopleA.Age=PeopleB.Age