2009-09-16 105 views
14

源表问题与SQL Server MERGE语句

Id, Name, Address 
1 A  #202 
1 A  #203 
1 A  #204 
2 A  #202 

目标表

合并

Id, Name, Address 
1 A  #202 
2 A  #202 

后,我用这SQL

create table #S (ID int, Name varchar(25) NULL, Address varchar(25) NULL) 
create table #T (ID int, Name varchar(25) NULL, Address varchar(25) NULL) 

INSERT #S values(1, 'A', '#202') 
INSERT #S values(1, 'A', '#203') 
INSERT #S values(1, 'A', '#203') 
INSERT #S values(1, 'A', '#204') 

INSERT #T values(1, 'A', NULL) 

MERGE #T USING 
    (
Select id, name, address 
from #S 
) AS S(id,name,address) 
on #T.id=S.id and #T.Name=S.Name 
when not matched THEN 
    INSERT values(S.id,S.Name, S.Address) 
when matched then 
    update set Address = S.Address; 
GO 

Select * from #T 
GO 

Select * from #S 
GO 

这将导致一个错误

消息8672,级别16,状态1,行18
MERGE语句试图更新或删除同一行多次。当目标行匹配多个源行时会发生这种情况。 MERGE语句不能多次更新/删除目标表的同一行。细化ON子句以确保目标行至多与一个源行匹配,或使用GROUP BY子句对源行进行分组。

我想从三个匹配值中的任何一个更新A中带有地址值的行。这个怎么做?

回答

22

#S中的四个值中的任何值都将与目标表的单个行值相匹配(#S中的所有值都具有id = 1且name ='A' - 因此它们全都匹配目标中的单个行),因此价值将被更新四次 - 这就是错误所说的,而且是绝对正确的。

你真的想在这里实现什么?

是否要将地址设置为源表中的第一个值?在你的子查询使用TOP 1条款:

MERGE #T 
USING (SELECT TOP 1 id, name, address FROM #S) AS S 
ON #T.id = S.id AND #T.Name = S.Name 
WHEN NOT MATCHED THEN 
    INSERT VALUES(S.id,S.Name, S.Address) 
WHEN MATCHED THEN 
    UPDATE SET Address = S.Address; 

你想将地址设置为从源表中的值的随机元素?在你的子查询使用TOP 1ORDER BY NEWID()条款:

MERGE #T 
USING (SELECT TOP 1 id, name, address FROM #S ORDER BY NEWID()) AS S 
ON #T.id = S.id AND #T.Name = S.Name 
WHEN NOT MATCHED THEN 
    INSERT VALUES(S.id,S.Name, S.Address) 
WHEN MATCHED THEN 
    UPDATE SET Address = S.Address; 

如果您符合四个源行到一个目标行,你永远不会得到一个有用的结果 - 你需要知道你真正想要的。

马克

+0

我想与地址值来更新行中的从三个匹配值 – 2009-09-16 16:32:32

+2

中的任何一个,但你如何确定它们使用哪一个? – HLGEM 2009-09-16 16:55:48

+2

我使用的Row_Number既是源代码也是目标(查看)。然后匹配条件包括附加条件,如果rownumbers是相同的(target.address isnull或(t.address = s.address)) – 2009-09-16 17:50:34

1

删除使用

select R.* 
from (SELECT Customer,Material,Received_date_time, 
row_number() over (Partition by Customer, Material 
order by Customer,Material,Received_date_time) as rn 
     from Customer_Table WHERE Status=0  
    ) as R 
where R.rn = 1 

因为你不能有重复的合并的dupicate,所以你总是要选择最新

+0

根据具体情况,这样做更有意义。也许你可以添加一个唯一的约束。 – 2015-12-01 14:18:20