SQL查询以查找不同行之间的文本差异

时间:2018-05-30 14:33:57

标签: sql sql-server

我有一张类似于以下内容的表格:

                     INITIAL TABLE
-------------------------------------------------------

ID        Date           Author      Data1       Data9
==  ================   ==========   ======= ... =======
1   2017-06-04 16:47   John Smith     Foo         Bar
2   2017-06-04 16:50   John Smith     Goo         Bar
3   2017-06-04 16:52   John Smith     Hoo         Car
4   2017-06-04 16:55   Bill Plith     Foo         Bar
5   2017-06-04 16:59   John Smith     Foo         Car
6   2017-06-04 17:04   Bill Plith     Foo         Bar

数据来自用户从中央源更改数据集。用户的名称,进行更改的日期时间以及所有数据字段的刷新'只要对任何数据字段进行了更改,就会将值附加到表中。

问题在于,手动检查每列以查看实际更改的位置非常繁琐。有时会对一个字段进行更改,有时会对多个字段进行更改,有时根本不会进行任何更改(如果用户单击"保存更改"实际上未进行任何更改,则新行将仍然被添加到表中。)

我想要查询表格以产生类似于以下内容的结果:

                     CHANGE TABLE
--------------------------------------------------------

      Date           Author              Changes
================   ==========   ========================
2017-06-04 16:50   John Smith   Data1 was changed to Goo
2017-06-04 16:52   John Smith   Data1 was changed to Hoo
2017-06-04 16:52   John Smith   Data9 was changed to Car
2017-06-04 16:55   Bill Plith   Data1 was changed to Foo
2017-06-04 16:55   Bill Plith   Data9 was changed to Bar
2017-06-04 16:59   John Smith   Data9 was changed to Car
2017-06-04 17:04   Bill Plith   Data9 was changed to Bar

还有一些事项需要注意:

  • 如果当前行与其上一行之间的初始表中的Data1-9未进行任何更改,则不应将任何行附加到更改表。
  • 如果具有相同日期(和时间)和作者的更改可以合并到“更改”列中的逗号分隔列表,那么这也是理想的。
  • 将订购初始表中的ID,但会丢失一些ID。例如,ID可以是1,2,3,4,7,8,10等。值可能会丢失,但初始表上的排序仍应基于ID(而不是日期)。

我认为这就是一切。提前感谢任何可以提供帮助的人,我还在学习SQL,所以如果我遗漏任何相关内容,请留下评论,我会填补空白!

2 个答案:

答案 0 :(得分:1)

您可以将case表达式与lag()一起使用。假设这些值都不是NULL

select c.date, c.author,
       stuff( ((case when data1 <> lag(data1) over (partition by date) then ', data1' else '' end) +
               (case when data2 <> lag(data2) over (partition by date) then ', data2' else '' end) +
               . . .
              ), 1, 2, '') as changes
from changes c;

可以修改它以处理NULL值,尽管这会使表达式复杂化。

答案 1 :(得分:0)

可以使用UNPIVOT运算符和LAG函数的default参数。

with
  unp as(
    select *
    from @Changes
    unpivot (
      Data For DataNam in (Data1,Data2,Data3,Data4,Data5,Data6,Data7,Data8,Data9)
    ) u
  ),
  a as(
    select *,
      lag(Data,1,Data) over(partition by DataNam order by [Date]) PrevData
    from unp
  )
select [Date], Author,DataNam+' was changed to '+Data Changes
from a
where Data!=PrevData
order by DataNam,[Date];

可以检查online