使用具有源条件的MERGE更新2列

时间:2017-06-19 08:43:16

标签: sql sql-server merge group-by

SQL SERVER 2014

我需要使用SourceTable

中的值更新TargetTable中的两列

SourceTbl

PersonNr |   Block  |   BlockReason |
---------|----------|---------------|
000001   |   1      |   abuse       | 
000001   |   1      |   age         | 
000001   |   0      |   memo        | 
000002   |   1      |   age         | 
000002   |   0      |               | 
000003   |   0      |               | 
000003   |   0      |               | 
000004   |   1      |   behaviour   | 
000005   |   0      |               | 

TargetTable

PersonNr |   Block  |   BlockReason |
---------|----------|---------------|
000001   |   0      |               | 
000001   |   0      |               | 
000002   |   0      |               | 
000002   |   0      |               | 
000004   |   1      |               | 
000005   |   0      |               | 

需要的结果:

PersonNr |   Block  |   BlockReason |
---------|----------|---------------|
000001   |   1      |   abuse       | 
000001   |   1      |   abuse       | 
000002   |   1      |   age         | 
000002   |   1      |   age         | 
000004   |   1      |   behaviour   |
000005   |   0      |               | 

{1}}人1得到的是无关紧要的, 至于BlockReason =' 1'中的一行。

我尝试过这个非常直接的更新:

Block

但结果是错误的结果行,其中Block和Reason分别更新:

UPDATE
    src
SET
    src.Block = '1', 
    src.BlockReason = targ.BlockReason
FROM
    SourceTbl src
INNER JOIN
    TargetTable targ
ON 
    src.PersonNr= targ.PersonNr
WHERE src.Block = '1'

接下来我尝试过:

PersonNr |   Block  |   BlockReason |
---------|----------|---------------|
000001   |  1       |   memo        | 

得到错误

MERGE INTO TargetTable AS TGT USING ( SELECT Block, BlockReason, PersonNr FROM SourceTbl GROUP BY Block, BlockReason, PersonNr ) AS SRC ON SRC.PersonNr= TGT.PersonNr AND SRC.Block= '1' WHEN MATCHED THEN UPDATE SET TGT.Block= SRC.Block, TGT.BlockReason= SRC.BlockReason;

有任何帮助吗?非常感谢!真正做到。完全。

3 个答案:

答案 0 :(得分:1)

您的查询的问题在于它提供了重复值,并且它尝试多次更新同一条记录。由于您没有使用任何聚合函数,因此子查询中的GROUP BY没有任何意义

我们取一个id(比如1)并检查你的查询出了什么问题。

src.PersonNr |   src.Block  |   src.BlockReason | tgt.PersonNr |   tgt.Block  |   tgt.BlockReason |
-------------|--------------|-------------------|--------------
    000001   |   1          |   abuse           | 000001       |       0      |                   |         
    000001   |   1          |   age             | 000001       |       0      |                   | 
    000001   |   1          |   abuse           | 000001       |       0      |                   |
    000001   |   1          |   age             |  000001      |       0      |                   |

您的查询会为您提供上述结果,并尝试针对每条记录更新目标表2次,包括滥用行为和下次年龄。

您可以尝试以下查询:

MERGE INTO TargetTable AS TGT
USING
(
 SELECT Block, BlockReason, PersonNr
 FROM(
       SELECT Block, BlockReason, PersonNr,ROW_NUMBER() OVER (PARTITION BY PersonNr  ORDER BY [YourPrimaryKey]) RN
       FROM SourceTbl ) X
 WHERE X.RN=1
) AS SRC
  ON 
    SRC.PersonNr= TGT.PersonNr AND 
    SRC.Block= '1' 
WHEN MATCHED THEN
UPDATE SET TGT.Block= SRC.Block, TGT.BlockReason= SRC.BlockReason;

答案 1 :(得分:0)

您的数据中有重复项。将另一个(或多个)列添加到ON的{​​{1}}子句中,该子句将有助于确定一个记录,或者在合并之前找到删除重复项的方法。

答案 2 :(得分:0)

UPDATE应该是这样的:

UPDATE
    targ
SET
    Block = '1', 
    BlockReason = src.BlockReason
FROM
    SourceTbl src
INNER JOIN
    TargetTable targ
ON 
    src.PersonNr= targ.PersonNr
WHERE src.Block = '1'

由于我们仅使用SourceTbl Block1的行,因此受此更新影响的行不应该结束我的理由Block0

如果SourceTbl中的多行连接到TargetTbl中的一行,但仍然存在一般性问题,这是不确定的,但是因为您已指出不需要确定性在这里,它不应该导致问题。