代码之家  ›  专栏  ›  技术社区  ›  toy

是否有一个SQL只显示从上一行更改的所有列的值?

  •  0
  • toy  · 技术社区  · 4 年前

    我有一个历史记录表,其中包含所有值,如果值发生更改,那么它将是一个新行。这就是一个例子

    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;
    
    1 回复  |  直到 4 年前
        1
  •  1
  •   Gordon Linoff    4 年前

    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 --如果是,那么你的结果无论如何都是模糊的。

        2
  •  1
  •   Himanshu Agrawal    4 年前

    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
    
    
        3
  •  1
  •   Laurenz Albe    4 年前

    对于每一列,使用如下表达式

    CASE WHEN lag(col) OVER (ORDER BY mod_date) IS DISTINCT FROM col THEN col END
    

    如果相邻行的列值相同,则将生成NULL。