利用主键跟踪现有 table 中几个列的变化?

Track the changes of a few columns in an existing table leveraging primary keys?

我目前正在尝试跟踪 SQL 服务器 table 中几个列的更改(我们称它们为 col1col2)。 table 不是 "updated/inserted/deleted" 随着时间的推移;新记录刚刚添加到其中(请参阅下面的 10/01 与 11/01)。

我的最终目标是 运行 一个 SQL 查询或存储过程,该查询或存储过程将使用遵循框架的主键突出显示超时更改:

PrimaryKey | ColumnName | BeforeValue | AfterValue | Date

例如

原文table:

+-------+--------+--------+--------+
|  PK1  |  Col1  |  Col2  |  Date  |
+-------+--------+--------+--------+
|   1   |    a   |    e   |  10/01 |  
|   1   |    b   |    e   |  11/01 |
|   2   |    c   |    e   |  10/01 |
|   2   |    d   |    f   |  11/01 |
+-------+--------+--------+--------+

输出:

+--------------+--------------+---------------+--------------+--------+
|  PrimaryKey  |  ColumnName  |  BeforeValue  |  AfterValue  |  Date  |
+--------------+--------------+---------------+--------------+--------+
|      1       |     Col1     |       a       |       b      |  11/01 |
|      2       |     Col1     |       c       |       d      |  11/01 |
|      2       |     Col2     |       e       |       f      |  11/01 |
+--------------+--------------+---------------+--------------+--------+  

感谢任何帮助。

这里有一些代码有点笨拙,但似乎有效,基本上我尝试为每一行找到具有不同值的较早的行。这样做两次,一次用于 Col1,一次用于 Col2。

为了让它工作,我必须添加一个唯一的 PK 字段,我不知道你是否有,你可以轻松地将其添加为身份字段,或者添加到你的真实 table,或者到用于计算的 table。

declare @TestTable table (PK int, PK1 int, Col1 varchar(1), Col2 varchar(1), [Date] date)

insert into @TestTable (PK, PK1, Col1, Col2, [Date])
  select 1, 1, 'a', 'e', '10 Jan 2018'
  union all select 2, 1, 'b', 'e', '11 Jan 2018'
  union all select 3, 2, 'c', 'e', '10 Jan 2018'
  union all select 4, 2, 'd', 'f', '11 Jan 2018'

  select T1.[Date], T1.PK1, 'Col1', T2.Col1, T1.Col1
  from @TestTable T1
  inner join @TestTable T2 on T2.PK = (
      select top 1 PK
      from @TestTable T21
      where T21.PK1 = T1.PK1 and T21.Col1 != T1.Col1 and T21.[Date] < T1.[Date]
      order by T21.[Date] desc
    )

  union all

  select T1.[Date], T1.PK1, 'Col2', T3.Col2, T1.Col2
  from @TestTable T1
  inner join @TestTable T3 on T3.PK = (
      select top 1 PK
      from @TestTable T31
      where T31.PK1 = T1.PK1 and T31.Col2 != T1.Col2 and T31.[Date] < T1.[Date]
      order by T31.[Date] desc
    )

  order by [Date], PK1