以 <旧值 - 新值 - 日期> 形式更改列值的历史记录
Posted
技术标签:
【中文标题】以 <旧值 - 新值 - 日期> 形式更改列值的历史记录【英文标题】:History of changing column values in the form <old value - new value - date> 【发布时间】:2018-06-14 19:27:33 【问题描述】:有一个这样的表(“param”列不是4,而是例如10):
+-------------+-------------+---------------------+--------+--------+--------+--------+
| primary_key | logical_key | change_time | param1 | param2 | param3 | param4 |
+-------------+-------------+---------------------+--------+--------+--------+--------+
| 1 | 1 | 14.06.2018 22:00:00 | x | 1 | f | 3 |
| 2 | 1 | 14.06.2018 22:00:01 | y | 4 | e | 32 |
| 3 | 1 | 14.06.2018 22:00:02 | t | 12 | r | 32 |
| 4 | 1 | 14.06.2018 22:00:02 | t | 45 | d | 40 |
+-------------+-------------+---------------------+--------+--------+--------+--------+
它存储更改的完整历史记录。 也就是说,当有一个单元格的逻辑更新时 - 将一行插入到表中 复制此logical_key上前一行的所有值, 在这个新行中,只有正在更新的单元格的值是新的。
需要以这种形式显示更改参数的历史:
+------------+-----------+-----------+---------------------+
| param_name | old_value | new_value | change_time |
+------------+-----------+-----------+---------------------+
| param1 | null | x | 14.06.2018 22:00:00 |
| param2 | null | 1 | 14.06.2018 22:00:00 |
| param3 | null | f | 14.06.2018 22:00:00 |
| param4 | null | 3 | 14.06.2018 22:00:00 |
| param1 | x | y | 14.06.2018 22:00:01 |
| param2 | 1 | 4 | 14.06.2018 22:00:01 |
| param3 | f | e | 14.06.2018 22:00:01 |
| param4 | 3 | 32 | 14.06.2018 22:00:01 |
| param1 | y | t | 14.06.2018 22:00:02 |
| param2 | 4 | 12 | 14.06.2018 22:00:02 |
| param3 | e | r | 14.06.2018 22:00:02 |
| param2 | 12 | 45 | 14.06.2018 22:00:02 |
| param3 | r | d | 14.06.2018 22:00:02 |
| param4 | 32 | 40 | 14.06.2018 22:00:02 |
+------------+-----------+-----------+---------------------+
我是这样实现的:
select * from
(select
'param1' as param_name,
nvl(to_char(lag(t.param1) over (order by t.primary_key)), 'null') as old_value,
nvl(to_char(t.param1), 'null') as new_value,
t.change_time
from my_table t
where t.logical_key = :pLogical_key) tt
where tt.old_value <> tt.new_value
union all
select * from
(select
'param2' as param_name,
nvl(to_char(lag(t.param2) over (order by t.primary_key)), 'null') as old_value,
nvl(to_char(t.param2), 'null') as new_value,
t.change_time
from my_table t
where t.logical_key = :pLogical_key) tt
where tt.old_value <> tt.new_value
/* union all etc. */
order by 4, 1
但这显然不是可以使用的东西。 我怎样才能让它被接受?
【问题讨论】:
Oracle 有一个UNPIVOT
子句,可以将列降为行。
【参考方案1】:
看看这是否有帮助 -
http://sqlfiddle.com/#!4/af100/29/0
CREATE TABLE Table1
(primary_key int, logical_key int, change_time varchar2(19), param1 varchar2(1), param2 int, param3 varchar2(1), param4 int)
;
INSERT ALL
INTO Table1 (primary_key, logical_key, change_time, param1, param2, param3, param4)
VALUES (1, 1, '14.06.2018 22:00:00', 'x', 1, 'f', 3)
INTO Table1 (primary_key, logical_key, change_time, param1, param2, param3, param4)
VALUES (2, 1, '14.06.2018 22:00:01', 'y', 4, 'e', 32)
INTO Table1 (primary_key, logical_key, change_time, param1, param2, param3, param4)
VALUES (3, 1, '14.06.2018 22:00:02', 't', 12, 'r', 32)
INTO Table1 (primary_key, logical_key, change_time, param1, param2, param3, param4)
VALUES (4, 1, '14.06.2018 22:00:02', 't', 45, 'd', 40)
SELECT * FROM dual
;
查询 -
select * from (
select col, lag(val,1,null) over (partition by col order by primary_key) as old_val, val as new_val, change_time from Table1
unpivot (val for col in (PARAM1,PARAM3))
union
select col, to_char(old_val) as old_val, to_char(new_val) as new_val, change_time from (
select col, lag(val,1,null) over (partition by col order by primary_key) as old_val, val as new_val, change_time from Table1
unpivot (val for col in (PARAM2,PARAM4))
)) where nvl(old_val,-1) <> new_val
order by 4,1;
结果 -
COL OLD_VAL NEW_VAL CHANGE_TIME
PARAM1 (null) x 14.06.2018 22:00:00
PARAM2 (null) 1 14.06.2018 22:00:00
PARAM3 (null) f 14.06.2018 22:00:00
PARAM4 (null) 3 14.06.2018 22:00:00
PARAM1 x y 14.06.2018 22:00:01
PARAM2 1 4 14.06.2018 22:00:01
PARAM3 f e 14.06.2018 22:00:01
PARAM4 3 32 14.06.2018 22:00:01
PARAM1 y t 14.06.2018 22:00:02
PARAM2 12 45 14.06.2018 22:00:02
PARAM2 4 12 14.06.2018 22:00:02
PARAM3 r d 14.06.2018 22:00:02
PARAM3 e r 14.06.2018 22:00:02
PARAM4 32 40 14.06.2018 22:00:02
【讨论】:
如果您解释了查询的作用,它可能会对 OP 有更多帮助。以上是关于以 <旧值 - 新值 - 日期> 形式更改列值的历史记录的主要内容,如果未能解决你的问题,请参考以下文章