2016-12-09 4 views
0

Учитывая следующие базы данных Oracle таблицы:Как вы меняете значения в столбце таблицы 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; 

это делает большинство из этого (по-прежнему нужен отдельный запрос для покрытия пересмотра = 1), но это очень медленно ,

Итак, мой вопрос: как мне максимально использовать Max здесь, чтобы вытащить самую высокую ревизию для каждой группы?

ответ

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; 
+1

Да это, кажется, работает. Так что этот ответ в сочетании с этим http://docs.oracle.com/cd/B28359_01/server.111/b28286/functions001.htm#SQLRF06174 (раздел об аналитических функциях) очень помог мне. –

+0

Оператор UPDATE не будет работать - предложение WITH не может предшествовать UPDATE, оно должно появиться после него. И использование NVL в состоянии ON в MERGE является рискованным - что, если 0 является одним из законных значений пересмотра? Лучше писать "или u.revision равно null и v.revision равно null". (На самом деле даже лучше было бы, если бы в таблице был первичный ключ!) В противном случае это правильный ответ, хорошая работа! – mathguy

+0

@mathguy, конечно, этого не произойдет. Это был просто мой беспорядок при построении ответа. Правильный ответ - это не обновление. – Kacper