左连接会产生额外的记录

时间:2013-12-10 16:18:02

标签: sql-server tsql left-join

这是一个基本的左连接问题,我已经阅读了很多文章,解释了发生了什么,但不知何故,解决方案并没有点击我的脑袋。我左边的桌子有独特的记录。我的右表有左边每条记录的几条记录。

在我读过的文章中,这经常被解释为左表有客户,右表有订单。这非常相似,但不完全是我所面对的。

在我的情况下,左表有唯一的记录,右边有重复的数据要迁移到左表所在的db中。所以我试着编写一个查询,它将加入两者共享的密钥,但我只需要右边的一条记录。我得到的结果当然有多个记录,因为左边的单个左边多次匹配。

我想我需要添加某种过滤功能,例如Top(1)但仍然在阅读/学习,并希望从此列表中的brainiacs获得反馈/指示。

以下是我正在使用的简单架构:

DECLARE @Customer TABLE
(
Id int,
Name varchar(50),
email varchar(50)
)

INSERT @Customer VALUES(1, 'Frodo', 'frodo@middleearth.org')
INSERT @Customer VALUES(2, 'Bilbo', 'Bilbo@middleearth.org')
INSERT @Customer VALUES(3, 'Galadriel', 'Galadriel@middleearth.org')
INSERT @Customer VALUES(4, 'Arwen', 'Arwen@middleearth.org')
INSERT @Customer VALUES(5, 'Gandalf', 'Gandalf@middleearth.org')

DECLARE @CustomerJobs TABLE
(
Id int,
email varchar(50),
jobname varchar(50)
)

INSERT @CustomerJobs VALUES(1, 'frodo@middleearth.org', 'RingBearer')
INSERT @CustomerJobs VALUES(2, 'frodo@middleearth.org', 'RingBearer')
INSERT @CustomerJobs VALUES(3, 'frodo@middleearth.org', 'RingBearer')
INSERT @CustomerJobs VALUES(4, 'frodo@middleearth.org', 'RingBearer')
INSERT @CustomerJobs VALUES(5, 'frodo@middleearth.org', 'RingBearer')
INSERT @CustomerJobs VALUES(6, 'Bilbo@middleearth.org', 'Burglar')
INSERT @CustomerJobs VALUES(7, 'Bilbo@middleearth.org', 'Burglar')
INSERT @CustomerJobs VALUES(8, 'Bilbo@middleearth.org', 'Burglar')
INSERT @CustomerJobs VALUES(9, 'Galadriel@middleearth.org', 'MindReader')
INSERT @CustomerJobs VALUES(10, 'Arwen@middleearth.org', 'Evenstar')
INSERT @CustomerJobs VALUES(10, 'Arwen@middleearth.org', 'Evenstar')
INSERT @CustomerJobs VALUES(11, 'Gandalf@middleearth.org', 'WhiteWizard')
INSERT @CustomerJobs VALUES(12, 'Gandalf@middleearth.org', 'WhiteWizard')


SELECT 
Cust.Name,
Cust.email,
CJobs.jobname

FROM 
@Customer Cust

LEFT JOIN @CustomerJobs CJobs ON
Cjobs.email = Cust.email

我正在玩row_number over partition(),因为我应该加入一个带有row_number而不是表本身的cte ???

我的另一个约束是我无法从右表中删除重复项。

所以我再次为这个简单化的问题道歉,并感谢你的帮助。

4 个答案:

答案 0 :(得分:1)

你必须想出一些人工方法,将每个电子邮件的第二个表减少到一行。例如:

SELECT 
Cust.Name,
Cust.ID,
Cust.email,
CJobs.jobname

FROM 
@Customer Cust

LEFT JOIN 
(select min(id) as id,email, jobname
from
@CustomerJobs
group by email, jobname) as  CJobs ON
Cjobs.email = Cust.email

但这几乎是随机的。有没有办法确定CustomerJobs表中哪一行是“正确的”?

答案 1 :(得分:1)

SELECT DISTINCT
Cust.Name,
Cust.email,
CJobs.jobname

FROM 
@Customer Cust

LEFT JOIN @CustomerJobs CJobs ON
Cjobs.email = Cust.email

DISTINCT关键字的附加内容可以为您提供所需的内容。

答案 2 :(得分:1)

不使用左连接,而是使用外部应用...然后您可以使用top子句来限制返回的行...

select
    Cust.Name
,   Cust.email
,   CJobs.jobname
from @Customer Cust
 outer apply (
    select top 1 *
    from @CustomerJobs CJobs
    where Cjobs.email = Cust.email
 ) cjobs;

答案 3 :(得分:1)

这将有效:

SELECT 
    Cust.Name,
    Cust.ID,
    Cust.email,
    CJobs.jobname
FROM @Customer Cust
LEFT JOIN 
    (SELECT DISTINCT email, jobname
    FROM @CustomerJobs) C2 ON C2.email = C.email