Oracle SQL--查找历史记录表中某列发生更改的最新数据

Oracle SQL--查找历史记录表中某列发生更改的最新数据,sql,oracle,window,Sql,Oracle,Window,我试图找到某列的值与前一状态不同的最新日期或版本 下面是我的历史记录表的示例: ID_OF_THING VERSION_NUMBER DATA 1 3 'Value2' 1 2 'Value2' 1 1 'Value1' 2 3 'Value3' 2 2

我试图找到某列的值与前一状态不同的最新日期或版本

下面是我的历史记录表的示例:

ID_OF_THING  VERSION_NUMBER   DATA
1            3                'Value2'
1            2                'Value2'
1            1                'Value1'
2            3                'Value3'
2            2                'Value2'
2            1                'Value1'
在本例中,_thing 1的id_的答案是版本2,因为它是最高的版本号,以前的版本号具有不同的数据。_thing 2的id_的答案是版本3

我甚至不知道如何在这里开始。如果我只想要最新的版本号,它将非常简单:

select ID_OF_THING, MAX(VERSION_NUMBER)
GROUP BY ID_OF_THING;

使用分析窗口函数最容易做到这一点,在本例中,查看下一行或上一行的数据是超前或滞后的。以下内容适用于将我使用的test表名替换为您所称的表名:

select 
    id_of_thing, 
    version_with_latest_change=max(version_number) 
from (
    select 
        id_of_thing, version_number, data, 
        previous_data=lag(data) over (
            partition by id_of_thing 
            order by version_number
        ) 
    from test
) x
where data <> previous_data
group by id_of_thing

请参见下面的示例,其中我使用WITH语句模拟了您的表。实际上,只需用表名替换tbL并删除with子句

查询查找值更改的最大版本,并使用id和版本从表中返回行。它还处理记录只有一个版本而没有任何更新的情况

    WITH tbl As
    (
    SELECT 1 As id, 3 As ver, 'Value2' As val FROM dual UNION ALL
    SELECT 1 As id, 2 As ver, 'Value2' As val FROM dual UNION ALL
    SELECT 1 As id, 1 As ver, 'Value1' As val FROM dual UNION ALL
    SELECT 2 As id, 3 As ver, 'Value3' As val FROM dual UNION ALL
    SELECT 2 As id, 2 As ver, 'Value2' As val FROM dual UNION ALL
    SELECT 2 As id, 1 As ver, 'Value1' As val FROM dual
    )
    SELECT t.*
      FROM tbl t
     WHERE (t.id, t.ver) IN 
    (
    SELECT z.id
         , MAX(z.ver) As max_ver
      FROM ( SELECT x.id
                  , x.ver
                  , x.val
                  , LAG(x.val) OVER (PARTITION BY x.id ORDER BY ver) As lag_val
                  , MIN(x.ver) OVER (PARTITION BY x.id) As min_ver
                  , MAX(x.ver) OVER (PARTITION BY x.id) As max_ver
               FROM tbl x
           ) z
     WHERE ( (z.min_ver = z.max_ver) -- where there is only one version
          OR (z.val != z.lag_val)    -- where the value has changed
           )
     GROUP BY z.id
    );