【问题标题】:SQL: Query to get the last change in value of a specific columnSQL:查询以获取特定列的值的最后更改
【发布时间】:2020-09-14 22:25:30
【问题描述】:

所以我有这张产品信息表。每次更改特定产品时,都会插入一个带有新值的新行,包括时间戳和修改它的用户。

为了显示信息,我搜索特定产品的最新行(由 product_id 列标识)。

但现在我需要知道谁是最后一个修改名为 status 的特定列的人。

假设我的表由这个组成

所以本质上我需要编写一个查询来告诉我该给定列的最后一次更改是什么时候。

product_id | name | status   | user | keyid
--------------------------------------------
598        | prrr | 0        | john | 10
598        | prod | 1        | jane | 11
456        | abcd | 2        | mac  | 12
598        | prdd | 2        | kate | 13
598        | rdpd | 2        | jane | 14
456        | prrr | 3        | john | 15
456        | abbb | 3        | kate | 16

所以产品598的最新信息是

598 rdpd 2 jane 14

但最后一个改变的人是凯特

产品456的最新信息是

456 abbb 3 kate 16

但最后一个改变的人是约翰

所以理想情况下,我想编写一个返回的查询

598 kate 13
456 john 15

我什至不知道如何编写这样的查询,所以我想知道是否有人可以在这里帮助我。

【问题讨论】:

    标签: sql select greatest-n-per-group gaps-and-islands


    【解决方案1】:

    如果你的数据库不支持窗口函数,逻辑就复杂一点。

    首先,请考虑以下查询,它会为您提供第一个 idkeys 行,其中每个 product_id 具有最新的 status

    select product_id, min(keyid)
    from mytable t
    where not exists (
        select 1 
        from mytable t1 
        where t1.product_id = t.product_id and t1.status <> t.status and t1.keyid > t.keyid
    )
    group by product_id
    

    这会返回:

    产品编号 |分钟(keyid) ---------: | ---------: 598 | 13 第456章15

    然后您可以使用此结果集来过滤表格:

    select t.*
    from mytable t
    where t.keyid in (
        select min(keyid)
        from mytable t
        where not exists (
            select 1 
            from mytable t1 
            where t1.product_id = t.product_id and t1.status <> t.status and t1.keyid > t.keyid
        )
        group by product_id
    )
    

    结果:

    产品编号 |姓名 |状态 |用户 |密钥ID ---------: | :--- | -----: | :--- | ----: 598 | prdd | 2 |凯特 | 13 第456章prrr | 3 |约翰 | 15

    Demo on DB Fiddle

    【讨论】:

    • 非常感谢您的回答!我一定会试一试的。但是我必须快速解决问题,并且由于没有答案,我最终将表修改为它将有更多的列来存储我需要的数据。但这会更优雅,更容易实现
    【解决方案2】:

    你可以使用窗口函数:

    select t.*
    from (select t.*, row_number() over (partition by productid order by keyid desc) as seqnum
          from (select t.*,
                       lag(status) over (partition by productid order by keyid) as prev_status
                from t
               ) t
          where prev_status is null or prev_status <> status
         ) t
    where seqnum = 1;
    

    最里面的子查询将每个值与其前一个值进行比较。中间子查询枚举状态发生变化的产品的每一行。外部查询过滤以获取最新的。

    【讨论】:

    • 我之前有过疑问,建议在哪里使用窗口函数。但是我的服务器数据库不支持窗口函数。
    猜你喜欢
    • 2022-01-12
    • 2022-01-07
    • 2019-07-29
    • 1970-01-01
    • 2020-02-13
    • 2018-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多