CREATE PROCEDURE [Dim].[Customer_Merge]
   @ExecutionLogId bigint
AS
BEGIN
DECLARE @dfValidFrom  datetime2(3) = '1900-01-01 00:00:00.000'
DECLARE @dfValidTo    datetime2(3) = '9999-12-31 00:00:00.000'
-- 1. Handle type 2 dimension update and insert rows in Dimension Customer.
-- Insert rows for updated and deleted data into Target table Dimension Customer.
INSERT INTO Dim.Customer(Customer_dkey, Customer_pkey, CustomerId_bkey, CustomerName, [Address], City, BusinessDate, RecordSource_audit, DateOfChange_audit, ValidFrom_meta, ValidTo_meta, IsCurrent_meta, IsDeleted_meta, IsInferred_meta, InsertExecutionLogId_audit) 
SELECT                   Customer_dkey, Customer_key,  CustomerId_bkey, CustomerName, [Address], City, BusinessDate, RecordSource_audit, DateOfChange_audit, ValidTo_meta,   @dfValidTo,   1,              IsDeleted_meta, IsInferred_meta, @ExecutionLogId
FROM                                                                                                               -- updated row's ValidTo_meta output value becomes ValidFrom_meta value in new inserted row.
(
  MERGE INTO Dim.Customer AS tgt -- Target table is Dim.Customer and Source table is Staging.Customer that will be Merge Into target with Insert or Update,
  USING                          -- where updated rows (via Merge ActionOutput = 'UPDATE') will be followed by the INSERT INTO above.
   (SELECT TOP(100) PERCENT Customer_dkey, CustomerId_bkey, CustomerName, [Address], City, BusinessDate, RecordSource_audit, DateOfChange_audit, IsCorrection_meta, IsDeleted_meta, IsInferred_meta
    FROM Staging.Customer
    ORDER BY CustomerId_bkey) AS src       -- Source scr is a staging table and Target tgt is a dimension table.
  ON tgt.Customer_dkey = src.Customer_dkey -- no tgt.IsCurrent_meta = 1 here.
  -- If new business key Then insert row with new data into Target table:
  WHEN NOT MATCHED BY TARGET THEN 
    INSERT (Customer_dkey,     CustomerId_bkey,     Customer_pkey, CustomerName,     [Address],     City,     BusinessDate,     RecordSource_audit,     DateOfChange_audit,     ValidFrom_meta, ValidTo_meta, IsCurrent_meta, IsDeleted_meta,     IsInferred_meta,     InsertExecutionLogId_audit)
    VALUES (src.Customer_dkey, src.CustomerId_bkey, 0,             src.CustomerName, src.[Address], src.City, src.BusinessDate, src.RecordSource_audit, src.DateOfChange_audit, @dfValidFrom,   @dfValidTo,   1,              src.IsDeleted_meta, src.IsInferred_meta, @ExecutionLogId)
  -- If existing business key is current and not inferred with different values from Source or is marked Deleted at Source Then update row in Target table:
  WHEN MATCHED AND tgt.IsCurrent_meta = 1 AND tgt.IsDeleted_meta = 0 AND tgt.ValidFrom_meta < src.DateOfChange_audit AND src.IsCorrection_meta = 0 AND 
   ((src.IsDeleted_meta = 0 AND tgt.IsInferred_meta = 0 AND (tgt.CustomerName != src.CustomerName OR ISNULL(tgt.[Address],'¤') != ISNULL(src.[Address],'¤') OR tgt.City != src.City OR ISNULL(tgt.BusinessDate,'1900-01-01') != ISNULL(src.BusinessDate,'1900-01-01'))) OR -- RecordSource_audit is a correction.
    (src.IsDeleted_meta = 1)) THEN
    UPDATE SET tgt.IsCurrent_meta   = 0,
               tgt.ValidTo_meta     = src.DateOfChange_audit, -- as a business date from operational system.
               tgt.UpdateTime_audit = SysUTCdatetime(),
               tgt.UpdateExecutionLogId_audit = @ExecutionLogId
    -- The updated rows in Target table become output and inserted as new rows in Target via INSERT INTO above.
    OUTPUT $Action AS ActionOutput, src.Customer_dkey, src.CustomerId_bkey, src.CustomerName, src.[Address], src.City, src.BusinessDate, src.RecordSource_audit, src.DateOfChange_audit, src.IsDeleted_meta, src.IsInferred_meta, inserted.ValidTo_meta, inserted.Customer_key
) AS MergeOutput                                         -- or DATEADD(day,1,inserted.ValidTo_meta) AS ValidTo_meta when new inserted row wants ValidFrom_meta to be at the next day.
WHERE MergeOutput.ActionOutput = 'UPDATE';               -- inserted.ValidTo_meta is the value from the updated row in target table, to become ValidFrom_meta value in new inserted row.
                                                         -- inserted.Customer_key is the value from the updated row in target table, to become Customer_pkey value in new inserted row.
-- 2. Handle overwrite of inferred rows or correction of data rows in Customer dimension.
MERGE INTO Dim.Customer AS tgt
USING Staging.Customer AS src
ON tgt.Customer_dkey = src.Customer_dkey AND tgt.IsCurrent_meta = 1 AND tgt.IsDeleted_meta = 0 AND (tgt.IsInferred_meta = 1 OR src.IsCorrection_meta = 1)
-- If existing business key is current and existing inferred row has different values from Source or a correction of data Then overwrite row in Target table:
WHEN MATCHED AND src.IsDeleted_meta = 0 AND (tgt.CustomerName != src.CustomerName OR ISNULL(tgt.[Address],'¤') != ISNULL(src.[Address],'¤') OR tgt.City != src.City OR ISNULL(tgt.BusinessDate,'1900-01-01') != ISNULL(src.BusinessDate,'1900-01-01') OR tgt.RecordSource_audit != src.RecordSource_audit) THEN
  UPDATE SET tgt.IsInferred_meta      = 0,
             tgt.CustomerName         = src.CustomerName,
             tgt.[Address]            = src.[Address],
             tgt.City                 = src.City,
             tgt.BusinessDate         = src.BusinessDate,
             tgt.RecordSource_audit   = src.RecordSource_audit,
             tgt.DateOfChange_audit   = src.DateOfChange_audit,
             tgt.CorrectionTime_audit = SysUTCdatetime(),
             tgt.UpdateTime_audit     = SysUTCdatetime(),
             tgt.UpdateExecutionLogId_audit = @ExecutionLogId;
END