从审计记录构建快照表

时间:2016-06-09 21:22:01

标签: sql-server sql-order-by audit-trail

我有一个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

我有一个CustomerHistory报告表,其中将填充每日ETL作业。它与Customer Table具有相同的字段,并带有附加字段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

我想解决方案将涉及在Audit表或递归CTE上的自联接。我很感激为开发此解决方案提供帮助。

注意:不幸的是,我没有使用触发器或更改Audit表架构的选项。查询性能不是问题,因为这将是每晚的ETL过程。

1 个答案:

答案 0 :(得分: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