2014-10-06 55 views
1

我尝试在两个表之间找到重复的行。此代码仅适用于记录不重复的情况:在sql中找到两个表之间的重复差异

(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 34PersonA表下例:

PERSONA

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

PersonB

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

我不明白你的要求是什么。你想查找记录出现在一张表中而不是另一张,或者重复记录在一张表中? – 2014-10-06 14:04:23

+0

@ZoffDino Dino我想查找出现在一张表中的记录,而不是其他包含重复记录的记录。只有记录不重复时,“除外”才显示差异。我需要像''all''这样的东西来找出哪个关系是1到1.对于表格:'表格1:约翰23,麦克17,约翰23'和'表格2:约翰23,麦克17'''除外'没有显示不同,但这两个表是不一样的。我需要找到缺失的记录,以便当我将这些记录添加到表中时,两个表都是相同的,例如。表1:约翰23,麦克17,约翰23'和'表1:约翰23,麦克17,约翰23'。 – rgb 2014-10-06 14:44:25

回答

5

您可以使用UNION ALL到Concat的表和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中的人, HOULD使用FULL OUTER JOIN作为戈登·利诺夫曾这样评价:

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,因为我正要给出基本相同的答案。 – user1429080 2014-10-06 14:09:11

+0

@Tim Schmelter您的解决方案找到重复的记录:'约翰45','罗伯特34','亚当46'。我想在'PeopleB'表中找到缺失的记录 - 'Robert 34'。该记录存在于两次'PeopleA'中,但只存在于'PeopleB'一次。 – rgb 2014-10-06 14:27:11

+0

@rgb:我编辑了答案。 – 2014-10-06 14:39:32

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 
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