2013-12-10 90 views
0

这是一个基本的左连接问题,我读了很多文章解释发生了什么,但不知何故解决方案没有点击我的脑海。我的左表有独特的记录。我的右表有几个记录在左边的每个记录。左加入结果额外记录

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

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

我想我需要添加某种过滤,如Top(1),但仍阅读/学习,并想从这个名单上的brainiacs反馈/方向。

以下是我与工作的一个简单的模式:

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

INSERT @Customer VALUES(1, 'Frodo', '[email protected]') 
INSERT @Customer VALUES(2, 'Bilbo', '[email protected]') 
INSERT @Customer VALUES(3, 'Galadriel', '[email protected]') 
INSERT @Customer VALUES(4, 'Arwen', '[email protected]') 
INSERT @Customer VALUES(5, 'Gandalf', '[email protected]') 

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

INSERT @CustomerJobs VALUES(1, '[email protected]', 'RingBearer') 
INSERT @CustomerJobs VALUES(2, '[email protected]', 'RingBearer') 
INSERT @CustomerJobs VALUES(3, '[email protected]', 'RingBearer') 
INSERT @CustomerJobs VALUES(4, '[email protected]', 'RingBearer') 
INSERT @CustomerJobs VALUES(5, '[email protected]', 'RingBearer') 
INSERT @CustomerJobs VALUES(6, '[email protected]', 'Burglar') 
INSERT @CustomerJobs VALUES(7, '[email protected]', 'Burglar') 
INSERT @CustomerJobs VALUES(8, '[email protected]', 'Burglar') 
INSERT @CustomerJobs VALUES(9, '[email protected]', 'MindReader') 
INSERT @CustomerJobs VALUES(10, '[email protected]', 'Evenstar') 
INSERT @CustomerJobs VALUES(10, '[email protected]', 'Evenstar') 
INSERT @CustomerJobs VALUES(11, '[email protected]', 'WhiteWizard') 
INSERT @CustomerJobs VALUES(12, '[email protected]', 'WhiteWizard') 


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

FROM 
@Customer Cust 

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

我与ROW_NUMBER玩弄过的分区()作为也许我应该与ROW_NUMBER在分区加入到热膨胀系数,而不是桌子本身?

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

所以再次我为简单的问题表示歉意,并感谢您的帮助。

+0

从右边只需要一条记录是什么意思?哪个记录?或者你是否只关心正确的桌子有任何记录但不关心哪个记录?在你的例子中,他们总是同一个人的记录;你的所有数据都是这种情况吗? – mayabelle

+0

我只需要添加到我的左数据库的工作名称,因为这是重复的权利,我不关心它使用哪个记录我只是想要它一次。 – GPGVM

回答

1

如果不使用LEFT JOIN,使用外部应用的...然后你可以使用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; 
+0

我在实践中发现,这往往比row_numbers或区别更快,但当然尝试所有选项以确保它依赖于它提出的查询计划。 –

+0

我发现每个人的答案都非常有帮助,但是这个教会了我一些新的东西,那就是APPLY运算符。从技术网:有两种形式的申请:交叉申请和外部申请。CROSS APPLY仅从外部表中返回生成表值函数结果集的行。 OUTER APPLY返回产生结果集的行和不包含表值函数生成的列中的NULL值的行。 – GPGVM

+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表中的哪一行是“正确”的?

+0

AFAIK /可以告诉细读他们是真正相同的数据,所以他们都是正确的,因此我只需要一个....任何一个。 – GPGVM

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

FROM 
@Customer Cust 

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

DISTINCT关键字的额外内容应该可以让你得到你想要的。

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

FYI截然不同,并在这里是多余的... –

+0

对不起,匆忙。是的,分组是不需要的。然而,我认为需要截然不同,因为在该表中有多个具有相同电子邮件和作业名称的行。 – mayabelle

+0

是的,你需要一个或另一个 - 即使在查询计划中,所有列和使用不同的分组也是等价的。 –