Wednesday, December 25, 2013

Efficient Way of Handling SCD Type 2 - Using Merge (Upsert) Statement

I feel happy that people around the globe reach my blog when they google for " SQL Server Upsert ". You can read the Basic Merge Post here. It was for beginners who want to use Merge for the first time and also for referral purpose. In that post, I only discussed about changed overwrites (Slowly Changing Dimension (SCD) Type 1), and now in this post, we shall see how to use Merge for SCD Type 2 (Dates and Flag) implementation.

Source Table: DEPT
CREATE TABLE [dbo].[DEPT]
(
            [DEPTNO] [numeric](2, 0) NULL,
            [DNAME] [varchar](14) NULL,
            [LOC] [varchar](13) NULL
)

Destination Table: DEPT_SCD2DATE
CREATE TABLE [dbo].[DEPT_SCD2DATE]
(
            [ID] [int] IDENTITY(1,1) NOT NULL,
            [DEPTNO] [numeric](2, 0) NULL,
            [DNAME] [varchar](14) NULL,
            [LOC] [varchar](13) NULL,
            [STARTDATE] [datetime] NULL,
            [ENDDATE] [datetime] NULL,
            [FLAG] [bit] NULL
)

Merge Code:


















INSERT INTO DEPT_SCD2DATE (DEPTNO, DNAME, LOC, STARTDATE, ENDDATE, FLAG)
SELECT DEPTNO, DNAME, LOC, STARTDATE, ENDDATE, FLAG FROM
(MERGE DEPT_SCD2DATE D
            USING DEPT S
                        ON (D.DEPTNO = S.DEPTNO)
            WHEN NOT MATCHED
            THEN
                        INSERT VALUES (S.DEPTNO, S.DNAME, S.LOC, GETDATE(), '2999-12-31', 1)
            WHEN MATCHED AND D.FLAG = 1 AND (D.DNAME <> S.DNAME OR D.LOC <> S.LOC)
            THEN
                        UPDATE SET D.FLAG = 0, D.ENDDATE = GETDATE()
                        OUTPUT $ACTION ACTIONOUT, S.DEPTNO, S.DNAME, S.LOC,
                        GETDATE() AS STARTDATE, '2999-12-31' AS ENDDATE, 1 AS FLAG
) AS MERGE_OUT
WHERE MERGE_OUT.ACTIONOUT = 'UPDATE';


Observation - Before Run 1:

Observation - After Run 1:

Observation - Before Run 2:

Observation - After Run 2:

Conclusion: Slowly Changing Dimension Type 2 is a method to maintain complete historical Data and Merge (Upsert) handles it easily. Hope this helps! Happy TSQL'ing :)

No comments:

Post a Comment