我有一个表,该表存储其他表中数据的历史值:
ObjectId | Value | UpdatedAt
1 | A | 2020-07-15
1 | B | 2020-07-16
1 | C | 2020-07-17
2 | A | 2020-07-15
2 | B | 2020-07-16
现在,我需要从此类表中生成“更改日志”,该表将显示旧值,新值以及更新发生的时间:
ObjectId | OldValue | NewValue | UpdatedAt
1 | A | B | 2020-07-16
1 | B | C | 2020-07-17
2 | A | B | 2020-07-16
不幸的是,我无法更改现有表的结构,也无法在其中放置旧值,我需要一个查询来提取它。
答案 0 :(得分:2)
您可以使用窗口功能lead()
对ObjectId
进行分区。这是demo。
select
ObjectId,
Value,
NewValue,
UpdatedAt
from
(
select
ObjectId,
Value,
lead(value) over (partition by ObjectId order by UpdatedAt) as NewValue,
lead(UpdatedAt) over (partition by ObjectId order by UpdatedAt) as UpdatedAt
from Table1
) subq
where NewValue is not null
order by ObjectId
输出:
| ObjectId Value NewValue UpdatedAt |
*-------------------------------------*
| 1 1 2 2020-07-16 |
| 1 2 3 2020-07-17 |
| 2 1 2 2020-07-16 |
答案 1 :(得分:1)
您可以使用窗口功能来获得结果。
DECLARE @historyTable table(ObjectId int, Value int, UpdatedAt date)
insert into @historyTable values
(1 , 1 ,'2020-07-15'),
(1 , 2 ,'2020-07-16'),
(1 , 3 ,'2020-07-17'),
(2 , 1 ,'2020-07-15'),
(2 , 2 ,'2020-07-16');
SELECT * from
(
SELECT objectid, value as oldvalue,
lead(value,1) over (partition by objectid order by updatedat) as newvalue,
lead(UpdatedAt,1) over (partition by objectid order by updatedat) as updatedat
FROM @historyTable
) as t
where t.updatedat is not null
+----------+----------+----------+------------+
| objectid | oldvalue | newvalue | updatedat |
+----------+----------+----------+------------+
| 1 | 1 | 2 | 2020-07-16 |
| 1 | 2 | 3 | 2020-07-17 |
| 2 | 1 | 2 | 2020-07-16 |
+----------+----------+----------+------------+
答案 2 :(得分:0)
with cte as (
select row_number() over (partition by objectid order by UpdatedAt ) rnk,[ObjectId], [Value], [UpdatedAt]
from T
)
select t1.ObjectId,t2.Value as OldValue ,t1.Value as NewValue ,t1.UpdatedAt
from (
select * from cte
where rnk <> 1
) t1
left join cte t2 on t1.objectid =t2.objectid and t1.rnk -1 = t2.rnk
表脚本:
CREATE TABLE T
([ObjectId] int, [Value] int, [UpdatedAt] datetime)
;
INSERT INTO T
([ObjectId], [Value], [UpdatedAt])
VALUES
(1, 1, '2020-07-15 00:00:00'),
(1, 2, '2020-07-16 00:00:00'),
(1, 3, '2020-07-17 00:00:00'),
(2, 1, '2020-07-15 00:00:00'),
(2, 2, '2020-07-16 00:00:00')
;
答案 3 :(得分:0)
with changeLogTemp as
(
select ROW_NUMBER() over (order by ObjectId,UpdatedAt ) row_number ,* from changeLog
)
select
l.ObjectId,
l.Value OldValue,
r.Value NewValue,
r.UpdatedAt
from changeLogTemp l
left join changeLogTemp r on l.ObjectId =r.ObjectId and l.row_number =r.row_number-1
where r.UpdatedAt is not null
您也可以使用Widowfunction (Lead())
解决这种情况
但是建议的解决方案非常简单
同时,对于行与两列或更多列之间的类似操作(computational and comparative
),它非常有用