[英]Is there an SQL to show only the value that got changed from the previous row for all columns?
I have a history table where it has all the values and if the value changed then it will be a new row.我有一个历史表,其中包含所有值,如果值发生更改,那么它将是一个新行。 This is the example这是例子
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
Then after a query I want the result to be like this然后在查询之后我希望结果是这样的
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
The point I'm trying to make is it's easier to check which value got changed after a timestamp.我想说明的一点是更容易检查时间戳后更改了哪个值。 The first row will always be there as it's default.第一行将始终存在,因为它是默认的。 Then the next row only shows create_user_id
and other_column
as it's changed from 1
to 2
and value1
to value2
然后下一行只显示create_user_id
和other_column
因为它从1
更改为2
,将value1
更改为value2
is_active
would just be empty as it's never changed is_active
将是空的,因为它从未改变
I read about lag
and partition
but it seems like it only works for one column as I want to check every column我读过lag
和partition
但它似乎只适用于一列,因为我想检查每一列
This is my example这是我的例子
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;
If you don't have too many columns then you can use lag separately for previous value of each column.如果您没有太多列,那么您可以单独为每列的先前值使用滞后。 you can also use alias for window as you will be running this for same window in order to make query easy to read.您还可以为窗口使用别名,因为您将在同一窗口运行它以使查询易于阅读。
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
For each column, use an expression like对于每一列,使用类似的表达式
CASE WHEN lag(col) OVER (ORDER BY mod_date) IS DISTINCT FROM col THEN col END
That will produce NULL if the column value is the same for neighboring rows.如果相邻行的列值相同,则将产生 NULL。
You are going to have to list all the columns, but I think the simplest expression is probably:您将不得不列出所有列,但我认为最简单的表达式可能是:
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;
You can construct the query for any audit table using information_schema.columns
to get all the columns in the table.您可以使用information_schema.columns
为任何审计表构造查询以获取表中的所有列。
This assumes that the column values are not NULL
-- and if they are, then your results are ambiguous anyway.这假设列值不是NULL
—— 如果它们是,那么你的结果无论如何都是不明确的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.