2016-11-18 38 views
2

我试图加载标准金博尔SCD2尺寸,利用我从以下网站获得了合并声明: http://www.kimballgroup.com/2008/11/design-tip-107-using-the-sql-merge-statement-for-slowly-changing-dimension-processing/MERGE试图更新或删除同一行不止一次

此合并声明除了处理新的实体相同之外。这将作为数据流中的直接插入来处理。此问题仅涉及同一业务密钥的多个版本。

当我执行MERGE语句SQL返回错误:

Msg 8672, Level 16, State 1, Line 3
The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row.
A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.

我使用SQL Server 2012:

SOURCE DATASET

enter image description here

目标数据集

enter image description here

这是我所期待的:

enter image description here

下面你可以找到脚本来重现问题:

CREATE TABLE SANDBOX.EHN.SOURCE_SCD2 (
    BUSINESS_KEY BIGINT 
,DESCRIPTION_A VARCHAR(2) 
,M_CRC   BIGINT 
,StartDATE  DATE 
,EndDATE  DATE) 



CREATE TABLE SANDBOX.EHN.TARGET_SCD2 (
    BUSINESS_KEY BIGINT 
,DESCRIPTION_A VARCHAR(2) 
,M_CRC   BIGINT 
,StartDATE  DATE 
,EndDATE  DATE) 



select * 
from SANDBOX.EHN.TARGET_SCD2 

truncate table SANDBOX.EHN.TARGET_SCD2 

INSERT INTO SANDBOX.EHN.SOURCE_SCD2 VALUES (1, 'B', 1, '2015-05-16', '2015-06-01') 
INSERT INTO SANDBOX.EHN.SOURCE_SCD2 VALUES (1, 'C', 2, '2015-06-01', '2015-06-11') 
INSERT INTO SANDBOX.EHN.SOURCE_SCD2 VALUES (1, 'D', 3, '2015-06-11', '9999-12-31') 

INSERT INTO SANDBOX.EHN.TARGET_SCD2 VALUES (1, 'A', 0, '2015-01-16', '9999-12-31') 



INSERT INTO SANDBOX.EHN.TARGET_SCD2 
    SELECT BUSINESS_KEY 
      ,DESCRIPTION_A 
     ,M_CRC 
     ,StartDATE 
     ,EndDATE 
FROM (
MERGE SANDBOX.EHN.TARGET_SCD2 D 
USING SANDBOX.EHN.SOURCE_SCD2 UPD 
ON(D.BUSINESS_KEY = UPD.BUSINESS_KEY) 
    WHEN MATCHED AND D.EndDATE = '9999-12-31' 
    THEN UPDATE SET D.EndDATE = UPD.EndDATE 
OUTPUT $Action Action_Out, UPD.BUSINESS_KEY 
         , UPD.DESCRIPTION_A 
        , UPD.M_CRC 
        , UPD.StartDATE 
        , UPD.EndDATE 
)AS MERGE_OUT 
WHERE MERGE_OUT.Action_Out = 'UPDATE' 

你能不能帮我解决这个问题?

+0

那么,错误消息是相当明确的:你有一个目标行,合并语句试图更新或删除多次。这不适用于合并声明。重写您的查询以确保一行只能是一个更新或删除语句的目标。 –

+0

谢谢你的回复,但这正是问题所在,我们知道'我们需要做什么,但不知道'如何'? –

+0

我有点困惑... AFAICT MERGE语句是顶级语句,不能像你在做的那样在派生表中使用。至少我没有在[documentation](https://msdn.microsoft.com/en-us/library/bb510625.aspx)中看到这种可能的用法。我在测试数据库(SS 2012)上执行了脚本,它给出了一个错误消息,我认为这是由于这个事实(*在包含合并的派生表的开始处,'D'*附近有错误的语法)。我错过了什么吗? –

回答

2

仅供上次更新使用;

INSERT INTO SANDBOX.EHN.TARGET_SCD2 
    SELECT BUSINESS_KEY 
      ,DESCRIPTION_A 
     ,M_CRC 
     ,StartDATE 
     ,EndDATE 
FROM (
MERGE SANDBOX.EHN.TARGET_SCD2 D 
USING SANDBOX.EHN.SOURCE_SCD2 UPD 
ON(D.BUSINESS_KEY = UPD.BUSINESS_KEY AND UPD.EndDATE = '9999-12-31') 
    WHEN MATCHED AND D.EndDATE = '9999-12-31' 
    THEN UPDATE SET D.EndDATE = UPD.StartDATE 
OUTPUT $Action Action_Out, UPD.BUSINESS_KEY 
         , UPD.DESCRIPTION_A 
         , UPD.M_CRC 
         , UPD.StartDATE 
         , UPD.EndDATE 
)AS MERGE_OUT 
WHERE MERGE_OUT.Action_Out = 'UPDATE' 

如果你想在你的目标表中的所有行SRC然后我用Nick.McDermaid

同意所有行使用;

UPDATE TRG 
    SET TRG.EndDate = SRC.StartDATE 
FROM SANDBOX.EHN.TARGET_SCD2 TRG 
JOIN (select SRC.BUSINESS_KEY, min(src.StartDATE)StartDATE 
     from SANDBOX.EHN.SOURCE_SCD2 SRC 
      group by SRC.BUSINESS_KEY 
     )SRC 
on (TRG.BUSINESS_KEY = SRC.BUSINESS_KEY 
     AND SRC.StartDate > TRG.StartDate) 
where 1 = 1 


INSERT SANDBOX.EHN.TARGET_SCD2 
SELECT * FROM SANDBOX.EHN.SOURCE_SCD2