如何在Oracle表的列中向下移动值?

时间:2016-12-09 10:13:42

标签: oracle merge analytic-functions

给出以下oracle数据库表:

group   revision    comment
1       1           1               
1       2           2 
1       null        null 
2       1           1               
2       2           2 
2       3           3 
2       4           4 
2       null        null 
3       1           1               
3       2           2 
3       3           3 
3       null        null 

我想将评论栏相对于版本在其组内向下移一步,以便我得到下表:

group   revision    comment
1       1           null            
1       2           1   
1       null        2  
2       1           null            
2       2           1   
2       3           2 
2       4           3 
2       null        4  
3       1           null            
3       2           1   
3       3           2 
3       null        3  

我有以下查询:

              

    MERGE INTO example_table t1
    USING example_table t2
    ON (
       (t1.revision = t2.revision+1 OR 
       (t2.revision = (
          SELECT MAX(t3.revision) 
          FROM example_table t3 
          WHERE t3.group = t1.group
       ) AND t1.revision IS NULL)
    ) 
    AND t1.group = t2.group)
    WHEN MATCHED THEN UPDATE SET t1.comment = t2.comment;

大部分内容(仍然需要单独的查询来覆盖revision = 1),但它非常慢。

所以我的问题是,如何尽可能有效地使用Max来为每个组提取最高版本?

1 个答案:

答案 0 :(得分:2)

我会使用lag而不是max

create table example_table(group_id number, revision number, comments varchar2(40));
insert into example_table values (1,1,1);
insert into example_table values (1,2,2);
insert into example_table values (1,3,null);
insert into example_table values (2,1,1);
insert into example_table values (2,2,2);
insert into example_table values (2,3,3);
insert into example_table values (2,4,null);

select * from example_table;

merge into example_table e
using (select group_id, revision, comments, lag(comments, 1) over (partition by group_id order by revision nulls last) comments1 from example_table) u
on (u.group_id = e.group_id and nvl(u.revision,0) = nvl(e.revision,0))
when matched then update set comments = u.comments1;

select * from example_table;