2016-11-18 37 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