[英]Is there an SQL to show only the value that got changed from the previous row for all columns?
我有一个历史表,其中包含所有值,如果值发生更改,那么它将是一个新行。 这是例子
name mod_date create_user_id is_active other_column
name1 2020-01-06 22:06:58+00 1 1 value1
name1 2020-01-06 22:07:01+00 2 1 value2
name2 2020-01-06 22:07:27+00 1 1 value2
然后在查询之后我希望结果是这样的
name mod_date create_user_id is_active other_column
name1 2020-01-06 22:06:58+00 1 1 value1
2020-01-06 22:07:01+00 2 value2
name2 2020-01-06 22:07:27+00 1
我想说明的一点是更容易检查时间戳后更改了哪个值。 第一行将始终存在,因为它是默认的。 然后下一行只显示create_user_id
和other_column
因为它从1
更改为2
,将value1
更改为value2
is_active
将是空的,因为它从未改变
我读过lag
和partition
但它似乎只适用于一列,因为我想检查每一列
这是我的例子
select name
from (select h.*,
lag(name) over(partition by h.id order by h.mod_date) lag_name
from history h
) h
where name <> lag_name;
如果您没有太多列,那么您可以单独为每列的先前值使用滞后。 您还可以为窗口使用别名,因为您将在同一窗口运行它以使查询易于阅读。
select name
from (select h.*,
lag(name) over main_window as lag_name,
lag(create_user_id) over main_window as prev_user_id,
lag(is_active) over main_window as prev_is_active,
lag(other_column) over main_window as prev_other_column
from history h
window main_window as (partition by h.id order by h.mod_date)
) h
where name <> lag_name
or create_user_id <> prev_user_id
or is_active <> prev_is_active
or other_column <> prev_other_column
对于每一列,使用类似的表达式
CASE WHEN lag(col) OVER (ORDER BY mod_date) IS DISTINCT FROM col THEN col END
如果相邻行的列值相同,则将产生 NULL。
您将不得不列出所有列,但我认为最简单的表达式可能是:
select nullif(name, lag(name) over (order by mod_date)) as name,
mod_date,
nullif(create_user_id, lag(create_user_id) over (order by mod_date)) as create_user_id,
nullif(is_active, lag(is_active) over (order by mod_date)) as is_active,
nullif(other_column, lag(name) over (order by mod_date)) as other_column
from t
order by mod_date;
您可以使用information_schema.columns
为任何审计表构造查询以获取表中的所有列。
这假设列值不是NULL
—— 如果它们是,那么你的结果无论如何都是不明确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.