如何处理SQL Server连接中的重复记录?

问题描述:

我一直试图在SQL Server中一起使用连接字段作为我的唯一标识符连接三个表,但我注意到它已经返回了重复的记录。如何处理SQL Server连接中的重复记录?

  • 表A具有25'003记录
  • 表B具有29'387记录
  • 表C具有22'938记录

目标是加入B和C到A.

结果共有48'732条记录。

这里是我的查询的一个片段:

Select 
    a.xxxx, a.yyyy, b.sdsd, c.dffgg 
From 
    [table A] a 
Left Join 
    [table B] b on a.pkey = b.pkey 
Left Join 
    [table C] c on a.pkey = c.pkey. 

表A:

PeriodRef OfficeCode OfficeDesc TaskServLineCode TaskServLineDesc ServLineDiv PartnerCode PartnerName ManagerCode ManagerName BillerCode BillerName ClientCode ClientName BusCatCode BusCatDesc GroupCode GroupDesc TaskCode TaskDesc TaskDateOpen TaskDateTerminate InvNumber InvDate LTDInv LTDFee LTDVat LTDCn LTDRec LTDPLFC YTDInv YTDFee YTDVat YTDCn YTDRec YTDPLFC PTDInv PTDFee PTDVat PTDCn PTDRec PTDPLFC CBal BalCurr Bal30 Bal60 Bal90 Bal120 Bal150 Bal180 CM Provision PM Provision CM Provision movement Start CY Provision YTD Provision movement 
201710 1 LAGOS A100 e a AAA xcv rg vgg AOA iyh erd2 tggtt yue jd kdk weeer INV Invoice NULL NULL 5yj 00:00.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
201710 1 LAGOS A100 e a AAA cbvc rfgt ghh ZZZZZ ssf 34ef etg assw kjkl kdk jdkjf INV Invoice NULL NULL 6uuj 00:00.0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
201710 1 LAGOS A100 e a AAA zcvv ffbb ddg EOK adf 23df sss asd ieel kdk dghjg;js CT07 sff 00:00.0 00:00.0 56 00:00.0 0 4837500 237500 0 5075000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

表B和C具有相同的架构。他们唯一的区别就是这个时期。

PS:这些表没有唯一的标识符,这就是为什么我连接了一些列以获取标识符的原因。谢谢大家。

+0

pkey不是唯一的...... – Backs

+0

如果您包含模式和样本数据以测试 –

+3

,它将有所帮助关于我们可以告诉您的是,表b和/或c中显然存在多行加入标准。 –

这是一个有点模糊的问题,“你如何处理重复记录加入?”,所以这里是一个非常通用的答案(这可能是你在找什么,也可能让你开始):

WITH UniqueKeys AS (
    SELECT DISTINCT pkey FROM [table A] 
    UNION 
    SELECT DISTINCT pkey FROM [table B] 
    UNION 
    SELECT DISTINCT pkey FROM [table C]) 
SELECT 
    u.pkey, 
    CASE WHEN a.pkey IS NOT NULL THEN 1 ELSE 0 END AS in_a, 
    CASE WHEN b.pkey IS NOT NULL THEN 1 ELSE 0 END AS in_b, 
    CASE WHEN c.pkey IS NOT NULL THEN 1 ELSE 0 END AS in_c 
FROM 
    UniqueKeys u 
    LEFT JOIN [table A] a ON a.pkey = u.pkey 
    LEFT JOIN [table B] a ON b.pkey = u.pkey 
    LEFT JOIN [table C] a ON c.pkey = u.pkey; 

这是我当我处理的,可能有重复或“失踪”在多个表的键数据的基本方法:

  • 做出确实存在键的主列表,在所有三个表。这里的关键是我使用UNION,因此删除了任何重复项;
  • 将此用作我的定位点,以便将LEFT JOIN添加到每个表中。

这会给我一个列表,显示每个键是否存在于表a,b或c中。

我想你想扩大这个,例如你可以添加一个约束条件,只有当源表中有重复项时才会列出这些关键字?

如果确实存在重复,例如pkey“XYZ123”在表A中存在四次,那么您可能需要将基本查询更改为GROUP BY u.pkey,并将CASE语句的MAX()值?你甚至可以通过使用SUM()来计算实例的数量,但是你需要避免“将结果乘以”。

所以您的查询现在看起来是这样的:

WITH UniqueKeys AS (
    SELECT DISTINCT pkey FROM [table A] 
    UNION 
    SELECT DISTINCT pkey FROM [table B] 
    UNION 
    SELECT DISTINCT pkey FROM [table C]) 
SELECT 
    u.pkey, 
    SUM(CASE WHEN a.pkey IS NOT NULL THEN a.instances ELSE 0 END) AS in_a, 
    SUM(CASE WHEN b.pkey IS NOT NULL THEN b.instances ELSE 0 END) AS in_b, 
    SUM(CASE WHEN c.pkey IS NOT NULL THEN c.instances ELSE 0 END) AS in_c 
FROM 
    UniqueKeys u 
    LEFT JOIN (SELECT COUNT(*) AS instances FROM [table A] WHERE pkey = u.pkey) a ON a.pkey = u.pkey 
    LEFT JOIN (SELECT COUNT(*) AS instances FROM [table B] WHERE pkey = u.pkey) b ON b.pkey = u.pkey 
    LEFT JOIN (SELECT COUNT(*) AS instances FROM [table C] WHERE pkey = u.pkey) c ON c.pkey = u.pkey 
GROUP BY 
    u.pkey; 

问题并不清楚。看看这是否有助于你。 无论你如何生成你的标识符,如果它具有超过一个对应的键,那么它将返回重复。

请检查3个表的计数。

select count(pkey) from [table A] 
select count(distinct pkey) from [table A] 
select count(pkey) from [table B] 
select count(distinct pkey) from [table B] 
select count(pkey) from [table C] 
select count(distinct pkey) from [table C] 

如果从表B和表C值的数量和重复计数不同,则意味着钥匙表B和表C.被复制所以你的加入总是返回多行,当你用表匹配A.