以 <旧值 - 新值 - 日期> 形式更改列值的历史记录

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 有更多帮助。

以上是关于以 <旧值 - 新值 - 日期> 形式更改列值的历史记录的主要内容,如果未能解决你的问题,请参考以下文章

数组合并递归旧值与新值

将 SaveChange 中的旧值和新值保存为 DbEntityEntry.Entity 以进行审计

如何在 laravel 中以编辑形式显示时间戳格式?

Ext.net 行编辑旧值和新值

Ajax,旧值先出现,然后新值出现

如何在文本框中使用 onchange() 事件获取旧值