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

SQL查询以查找不同行之间的文本差异,sql,sql-server,Sql,Sql Server,我有一张类似以下的桌子: INITIAL TABLE ------------------------------------------------------- ID Date Author Data1 Data9 == ================ ========== ======= ... ======= 1 2017-06-04 16:47 John Smith

我有一张类似以下的桌子:

                     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
数据来自用户从中心源更改数据集。每当对任何数据字段进行更改时,都会将用户名、更改的日期时间以及所有数据字段值的刷新追加到表中

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

我要做的是查询该表以生成类似于以下内容的结果:

                     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,因此如果我遗漏了任何相关内容,请留下评论,我将填补空白

您可以使用带有
lag()
的巨型
大小写
表达式。假设所有值都不为空

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;
选择c.date、c.author、,
填充((当数据1滞后(数据1)超过(按日期划分)时,则',数据1'否则''结束)+
(当data2滞后(data2)超过(按日期划分)时,则',data2'else'结束)+
. . .
),1,2',)作为更改
来自变化c;

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

可以使用UNPIVOT运算符和LAG函数的
默认
参数

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];

这可以检查。

使用插入后触发器更新新的更改列。您可以使用LAG函数检索前一行的ID以比较每一列。你将不得不使用一个巨大的案例陈述来连接你对每一个变更的评论。也许有人能想出更干净的解决方案。我最后用了一个变体来解决我的问题。感谢您的快速回复!