选择最大版本值

时间:2017-10-23 22:51:24

标签: sql oracle

我需要根据给定记录的某个版本提取数据。我想根据ID的第一个用户的最终保存提取最大版本。这可能吗?
- 在我的模拟中,我的版本号为1,2,3,但数字实际上是在我的数据库中随机分配的。

我正在尝试使用:

select id, max(version) over partition by id 
from t1

这是我的数据: T1

ID    User   Version  
1     123      1  
1     123      2  
1     123      3  
1     456      4  
1     456      5  
1     789      6  
2     452      1  
2     452      2  
2     587      3  
2     123      4  
3     901      1  
3     767      2  
3     456      3  

这是我想要提取的内容: T1

ID    User   MaxVersion  
1     123      3  
2     452      2  
3     901      1  

3 个答案:

答案 0 :(得分:2)

我想你想要:

select t1.*
from (select id,
             row_number() over (partition by id, user order by version desc) as seqnum,
             max(user) keep (dense_rank first order by version) over (partition by id) as first_user
       from t1
     ) t1
where seqnum = 1 and user = first_user;

您需要单独查找用户和最后一条记录。

编辑:

如果您需要"首先"最终版本,我会选择:

select t1.*
from (select t1.*,
             min(case when user <> first_user then version end) over (partition by id) as last_version_plus_1
      from (select id,
                   max(user) keep (dense_rank first order by version) over (partition by id) as first_user
             from t1
           ) t1
      where seqnum = 1 and user = first_user
     ) t1
where version < max_version;

或者,您可以使用相关子查询执行此操作:

select t1.*
from t1
where t1.user = (select min(tt1.user) keep (dense_rank first order by tt1.version)
                 from t1 tt1
                 where tt1.id = t1.id
                ) and
      t1.version < (select min(tt1.version)
                    from t1 tt1
                    where tt1.id = t1.id and tt1.user <> t1.user
                   );

这是老式的&#34;方法(预解析函数)。但它完全捕捉到了这个想法。第一个确保用户是第一个用户。第二个确保版本来自该用户的第一个记录。

答案 1 :(得分:1)

在Oracle 12.1及更高版本中,match_recognize可以快速完成此类要求。 (与分析函数解决方案相比,一个好处是max(version)仅为每个ID的一个用户计算,而不需要子查询来实现此效率。

match_recognize子句按id分区,并在每个id内按版本(升序)排序。然后“匹配”仅来自分区的开头(^子句中的pattern),并且仅包含与第一行具有相同id的行(在按id分区。该id的所有其他行都将被忽略。然后收集输出的最后一个版本值。

注意:这假定,如果对于给定的ID,第一个用户更改为第二个,第三个等,但随后恢复为第一个用户,中的最高版本号需要> FIRST 该用户的行集。如果需要该用户的所有行中的最高版本号,则可以相应地更改查询(特别是PATTERN子句需要更改)。

with
  inputs ( id, usr, ver ) as (  
    select 1, 123, 1 from dual union all  
    select 1, 123, 2 from dual union all  
    select 1, 123, 3 from dual union all
    select 1, 456, 4 from dual union all
    select 1, 456, 5 from dual union all
    select 1, 789, 6 from dual union all
    select 2, 452, 1 from dual union all
    select 2, 452, 2 from dual union all
    select 2, 587, 3 from dual union all
    select 2, 123, 4 from dual union all
    select 3, 901, 1 from dual union all
    select 3, 767, 2 from dual union all
    select 3, 456, 3 from dual
  )
-- End of simulated inputs (not part of the solution).
-- SQL query begins BELOW THIS LINE. Use your actual table and column names.
select id, usr, ver
from   inputs
match_recognize (
  partition by id
  order by ver
  measures last(usr) as usr,
           last(ver) as ver
  pattern ( ^ a+ )
  define  a as usr = first(usr)
);

ID  USR  VER
--  ---  ---
 1  123    3
 2  452    2
 3  901    1

修改

为了完整性,如果用户可能出现在非连续行上,那么PATTERN应该是什么样子,并且对于给定id,该用户的最后一次出现(即使非连续)必须是考虑:

...
    pattern ( ^ a (x* a)? )
...

此处分区中的第一行是 a ,如果相同的用户再次出现在同一id,则至少还有一个 a 行; last 这样的行被模式的可选部分捕获,并且x*上有贪婪的匹配。

答案 2 :(得分:0)

select rnk,id, user,mv from (select rownum as rnk,id,user,max(version) from T1

group by id, user )where rnk=1;