2016-06-09 50 views
2

我有一個Customer表,其結構如下。從審計記錄構建快照表

CustomerId Name Address Phone 
1   Joe 123 Main NULL 

我也有一個Audit表跟蹤更改Customer表。

Id Entity EntityId Field OldValue  NewValue  Type AuditDate 
1 Customer 1   Name  NULL   Joe   Add 2016-01-01 
2 Customer 1   Phone NULL   567-54-3332 Add 2016-01-01 
3 Customer 1   Address NULL   456 Centre Add 2016-01-01 
4 Customer 1   Address 456 Centre 123 Main  Edit 2016-01-02 
5 Customer 1   Phone 567-54-3332 843-43-1230 Edit 2016-01-03 
6 Customer 1   Phone 843-43-1230 NULL   Delete 2016-01-04 

我將每日ETL作業被填充的CustomerHistory報告表。它與客戶表具有相同的字段,其他字段爲SnapShotDate

我需要編寫一個查詢,其中包含Audit表中的記錄,如下所示,轉換並插入CustomerHistory

CustomerId Name Address  Phone   SnapShotDate 
1   Joe 456 Centre 567-54-3332 2016-01-01 
1   Joe 123 Main  567-54-3332 2016-01-02 
1   Joe 123 Main  843-43-1230 2016-01-03 
1   Joe 123 Main  NULL   2016-01-04 

我想解決方案將涉及審計表或遞歸CTE的自聯接。我希望在開發此解決方案方面有任何幫助。

注意:不幸的是,我沒有選擇使用觸發器或更改審計表模式。查詢性能不是問題,因爲這將是夜間ETL過程。

+0

只是要清楚,你已經有一個ETL填充CustomerHistory,你爲什麼要使用下面的腳本從審計表填充它?順便說一句,這是一個有趣的謎題:) – FLICKER

+0

@FLICKER - 爲了澄清,我需要建立一個查詢,通過ETL過程填充CustomerHistory表。目前尚未填入數據。 – Thracian

+0

明白了。我即將找到解決方案 – FLICKER

回答

0

您可以使用下面的腳本。

DROP TABLE #tmp 

CREATE TABLE #tmp (
    id INT Identity 
    , EntityId INT 
    , NAME VARCHAR(10) 
    , Address VARCHAR(100) 
    , Phone VARCHAR(20) 
    , Type VARCHAR(10) 
    , SnapShotDate DATETIME 
    ) 

;with cte1 as (
select AuditDate, EntityId, Type, [Name], [Address], [Phone] 
from 
    (select AuditDate, EntityId, Type, Field, NewValue from #Audit) p 
pivot 
    (
    max(NewValue) 
    for Field in ([Name], [Address], [Phone]) 
    ) as xx 
) 
insert into #tmp (EntityId, Name, Address, Phone, Type, SnapShotDate) 
select EntityId, Name, Address, Phone, Type, AuditDate 
from cte1 


-- update NULLs columns with the most recent value 
update #tmp 
set Name = (select top 1 Name from #tmp tp2 
      where EntityId = tp2.EntityId and Name is not null 
      order by id desc) 
where Name is null 

update #tmp 
set Address = (select top 1 Address from #tmp tp2 
       where EntityId = tp2.EntityId and Address is not null 
       order by id desc) 
where Address is null 

update #tmp 
set Phone = (select top 1 Phone from #tmp tp2 
      where EntityId = tp2.EntityId and Phone is not null 
      order by id desc) 
where Phone is null 

創建Test Data

CREATE TABLE #Customer (
    CustomerId INT 
    , NAME VARCHAR(10) 
    , Address VARCHAR(100) 
    , Phone VARCHAR(20) 
    ) 

INSERT INTO #Customer 
VALUES (1, 'Joe', '123 Main', NULL) 

CREATE TABLE #Audit (
    Id INT 
    , Entity VARCHAR(50) 
    , EntityId INT 
    , Field VARCHAR(20) 
    , OldValue VARCHAR(100) 
    , NewValue VARCHAR(100) 
    , Type VARCHAR(10) 
    , AuditDate DATETIME 
    ) 

insert into #Audit values 
(1, 'Customer', 1,   'Name'  ,NULL   ,'Joe'   ,'Add' ,'2016-01-01'), 
(2, 'Customer', 1,   'Phone' ,NULL   ,'567-54-3332' ,'Add' ,'2016-01-01'), 
(3, 'Customer', 1,   'Address' ,NULL   ,'456 Centre' ,'Add' ,'2016-01-01'), 
(4, 'Customer', 1,   'Address' ,'456 Centre' ,'123 Main'  ,'Edit' ,'2016-01-02'), 
(5, 'Customer', 1,   'Phone' ,'567-54-3332' ,'843-43-1230' ,'Edit' ,'2016-01-03'), 
(6, 'Customer', 1,   'Phone' ,'843-43-1230' ,NULL   ,'Delete' ,'2016-01-04'), 
(7, 'Customer', 2,   'Name'  ,NULL   ,'Peter'  ,'Add' ,'2016-01-01'), 
(8, 'Customer', 2,   'Phone' ,NULL   ,'111-222-3333' ,'Add' ,'2016-01-01'), 
(8, 'Customer', 2,   'Address' ,NULL   ,'Parthenia' ,'Add' ,'2016-01-01') 

結果

EntityId Name Address  Phone   Type SnapShotDate 
1   Joe  456 Centre 567-54-3332  Add  2016-01-01 
1   Joe  123 Main 843-43-1230  Edit 2016-01-02 
1   Joe  123 Main 843-43-1230  Edit 2016-01-03 
1   Joe  123 Main 843-43-1230  Delete 2016-01-04 
+0

謝謝你的迴應。當我運行查詢時,我得到了一個不同的結果集(見下文)。它有一排喬,其餘是彼得和快照日期不準確。 此外,解決方案需要每個字段的更新聲明。對於3個字段不是什麼大問題,但是當字段更多時,會有很多重複的代碼。我認爲我們可以想出一個使用自聯接(或遞歸CTE)的更精簡的解決方案。再次感謝您的初步努力。 – Thracian

+0

ID \t ENTITYID \t NAME \t地址\t電話\t類型\t SnapShotDate 喬\t 456中心\t 567-54-3332 \t添加\t 2016年1月1日00:00:00.000 彼得\t帕西尼亞\t \t 111-222-3333添加\t 2016年1月1日00:00:00.000 \t 1彼得\t 123主\t \t 843-43-1230編輯\t 2016-01-02 00:00:00。000 \t 1彼得\t 123主\t \t 843-43-1230編輯\t 2016年1月3日00:00:00.000 \t 1彼得\t 123主\t \t 843-43-1230刪除\t 2016-01 -04 00:00:00.000 – Thracian

+0

在第一個查詢中,填充臨時表時,使用ORDER BY EntityId,AuditDate。讓我知道它是如何工作的 – FLICKER