Sql server 左连接会产生额外的记录

Sql server 左连接会产生额外的记录,sql-server,tsql,left-join,Sql Server,Tsql,Left Join,这是一个基本的左连接问题,我已经读了很多文章解释了发生了什么,但不知何故,解决方案并没有在我的脑海中点击。我的左表有唯一的记录。我右边的表有几个记录,左边的每个记录都有几个记录 在我读过的文章中,这经常被解释为左表有客户,右表有订单。这很相似,但并不完全是我所面临的 在我的情况下,左表有唯一的记录,右表有重复的数据要迁移到左表所在的数据库中。因此,我试图编写一个查询,该查询将连接到双方共享的密钥上,但我只需要右侧的一条记录。我得到的结果当然有多个记录,因为左边的一个匹配右边的多次 我想我需要添加

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

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

在我的情况下,左表有唯一的记录,右表有重复的数据要迁移到左表所在的数据库中。因此,我试图编写一个查询,该查询将连接到双方共享的密钥上,但我只需要右侧的一条记录。我得到的结果当然有多个记录,因为左边的一个匹配右边的多次

我想我需要添加一些过滤功能,如Top(1),但仍在阅读/学习,并希望从列表中的智囊团那里获得反馈/指导

以下是我正在使用的简单模式:

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
我在玩弄分区上的行数(),因为也许我应该用分区上的行数而不是表本身加入cte

另一个限制是我不能从正确的表中删除重复项


因此,我再次为这个过于简单的问题道歉,并感谢您的帮助。

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

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

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

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

额外的DISTINCT关键字应该可以满足您的需要


DISTINCT关键字的附加值应该可以满足您的需要。

使用外部应用程序,而不是使用左连接。。。然后可以使用
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;

不要使用左连接,而是使用外部应用。。。然后可以使用
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;
这将有助于:

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
这将有助于:

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


只需要右边的一条记录是什么意思?哪张唱片?或者您只关心正确的表是否有任何记录,而不关心哪个记录?在您的示例中,它们始终是同一个人的同一记录;您的所有数据都是这样吗?我只需要在左侧数据库中添加jobname,因为它在右侧重复出现,所以我不在乎它使用哪一条记录,我只需要一次。只需要从右侧添加一条记录有什么意义?哪张唱片?或者您只关心正确的表是否有任何记录,而不关心哪个记录?在您的示例中,它们始终是同一个人的同一记录;您的所有数据都是这样吗?我只需要在左侧数据库中添加jobname,因为它在右侧是重复的,所以我不在乎它使用哪一条记录,我只想要一次。我在实践中发现,这往往比行数或距离快,但当然,请尝试所有选项,因为这取决于它提出的查询计划。我发现每个人的答案都非常有用,但这一个告诉了我一些新的东西,即应用运算符。来自科技网:申请有两种形式:交叉申请和外部申请。交叉应用仅返回从表值函数生成结果集的外部表中的行。外部应用程序返回生成结果集的行和不生成结果集的行,表值函数生成的列中的值为空。基本上,交叉应用程序返回内部连接,就像外部应用程序返回左连接一样。我在实践中发现,这往往比行数或distincts快,但当然,请尝试所有选项,因为这取决于它提出的查询计划。我发现每个人的答案都非常有用,但这一个告诉了我一些新的东西,即应用运算符。来自科技网:申请有两种形式:交叉申请和外部申请。交叉应用仅返回从表值函数生成结果集的外部表中的行。外部应用程序返回生成结果集的行和不生成结果集的行,表值函数生成的列中的值为空。基本上,交叉应用程序返回内部连接,就像外部应用程序返回左连接一样。对不起,我很忙。是的,不需要分组。但是,我认为需要使用distinct,因为该表中有多行具有相同的电子邮件和作业名称。是的,您需要一行或另一行-按所有列分组和使用distinct是等效的,即使在查询计划中也是如此。很好的一点,两种方法都可以完成相同的任务。有趣的是,查询计划也是一样的。对不起,我赶时间。是的,不需要分组。但是,我认为需要使用distinct,因为该表中有多行具有相同的电子邮件和作业名称。是的,您需要一行或另一行-按所有列分组和使用distinct是等效的,即使在查询计划中也是如此。很好的一点,两种方法都可以完成相同的任务。很有意思的是,查询计划也是一样的。AFAIK/可以告诉我们,仔细阅读数据时,它们是完全相同的,所以它们都是正确的,因此我只需要一个……任何一个。AFAIK/可以告诉我们,仔细阅读数据时,它们是完全相同的,所以我只需要一个……任何一个。