SQL - 组合2行,不平整数据并将列转换为单独的行

时间:2014-01-19 18:36:47

标签: sql tsql stored-procedures

我目前正在使用类似于以下的审核日志表:

ID  |  EventKey            |  AccessID  |  AccessType  |  Status  |  Final
------------------------------------------------------------------------------
1   | ABC123               |  NULL      |  123         |  335     |   OK
2   | ABC123               |  985521    |  NULL        |  66      |   OK
....
41  | ABC456               |  NULL      |  456         |  335     |   OK
42  | ABC456               |  113228    |  NULL        |  66      |   OK

我需要做的是取消这些数据,并基本上根据两行的值返回4行

即。 -

Field      |  FieldValuePrevious  |  FieldValueChanged  | EventKey    
------------------------------------------------------------------------------
AccessID   | NULL                 | 985521              | ABC123       
AccessType | 123                  | NULL                | ABC123             
Status     | 335                  | 66                  | ABC123               
Final      | OK                   | OK                  | ABC123       

如果通过内联SQL很难做到,我也可以转换为存储过程。

1 个答案:

答案 0 :(得分:1)

基本上,您必须单独执行每个字段。让我演示如何使用SQL Server 2012执行此操作:

select 'AccessId' as field, prev_accessid as ValuePrevious,
       accessid as ValueChanged, eventkey
from (select id, eventkey, accessid,
             lag(id) over (partition by eventkey order by id) as prev_id
             lag(accessid) over (partition by eventkey order by id) as prev_accessid
      from auditlog al
     ) al
where prev_id is not null and
      not (prev_accessid = accessid or prev_accessid is null and accessid is null);

编辑:

您可以使用相关子查询替换lag()函数:

select 'AccessId' as field, prev_accessid as ValuePrevious,
       accessid as ValueChanged, eventkey
from (select id, eventkey, accessid,
             lag1.id as prev_id
             lag1.accessid as prev_accessid
      from (select al.*,
                   (select top 1 id
                    from auditlog al2
                    where al2.eventkey = al.eventkey and
                          al2.id < al.id
                    order by al2.id desc
                   ) as lag1id
            from auditlog al
           ) al left outer join
           auditlog lag1
           on al.lag1id = lag1.id
     ) al
where prev_id is not null and
      not (prev_accessid = accessid or prev_accessid is null and accessid is null);