Sql 以的形式更改列值的历史记录
有一个此类表格,参数列不是4,而是10:Sql 以的形式更改列值的历史记录,sql,oracle,pivot,window-functions,Sql,Oracle,Pivot,Window Functions,有一个此类表格,参数列不是4,而是10: +-------------+-------------+---------------------+--------+--------+--------+--------+ | primary_key | logical_key | change_time | param1 | param2 | param3 | param4 | +-------------+-------------+---------------------+--
+-------------+-------------+---------------------+--------+--------+--------+--------+
| 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 |
+-------------+-------------+---------------------+--------+--------+--------+--------+
它存储更改的完整历史记录。
也就是说,当对一个单元格进行逻辑更新时,一行被插入到表中
复制此逻辑_键上上一行的所有值,
在这个新行中,只有被更新的单元格的值是新的
有必要以这种形式显示更改参数的历史记录:
+------------+-----------+-----------+---------------------+
| 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
但这显然不是可以使用的东西。
我如何才能让它被接受?看看这是否有助于-
查询-
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;
Oracle有一个UNPIVOT子句,可以将列降到行。如果您解释一下查询的作用,它可能会对OP有更多帮助。
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