2013-08-28 3 views
2

У меня возникла проблема с внедрением LEAD/LAG с разделом.Перегородка с использованием Lead в Oracle

Ниже приведен пример и ожидаемый результат

create table trd(
    key number, 
    book number, 
    prd_key number, 
    direction varchar2(2), 
    trdtime date, 
    price number) 




insert into trd values(1234,115,133864,'B','17-07-2013 18:18:00',108.859); 
insert into trd values(1235,115,133864,'S','17-07-2013 18:18:00',108.859); 
insert into trd values(1245,115,133864,'S','17-07-2013 18:18:00',108.859); 
insert into trd values(1236,115,133864,'B','15-07-2013 18:18:00',108.872); 
insert into trd values(1237,115,133864,'S','15-07-2013 18:18:00',108.866); 
insert into trd values(1247,115,133864,'S','15-07-2013 18:18:00',108.866); 
insert into trd values(1238,115,133864,'S','14-07-2013 18:18:00',107.86); 
insert into trd values(1239,115,133864,'S','14-07-2013 18:17:00',108.86); 
insert into trd values(1240,115,133864,'B','14-07-2013 18:12:00',109.86); 
insert into trd values(1241,115,133864,'B','14-07-2013 18:17:00',110.86); 

Мне нужно вернуть значение что-то вроде этого:

Key Book Prd_Key Dir TrdTime    Price  NextPrice 
1234 115 133864 B 7/17/2013 6:18:00 PM 108.859 108.866 
1235 115 133864 S 7/17/2013 6:18:00 PM 108.859 108.872 
1245 115 133864 S 7/17/2013 6:18:00 PM 108.859 108.872 
1236 115 133864 B 7/15/2013 6:18:00 PM 108.872 108.86 
1237 115 133864 S 7/15/2013 6:18:00 PM 108.866 110.86 
1247 115 133864 S 7/15/2013 6:18:00 PM 108.866 110.86 
1238 115 133864 S 7/14/2013 6:18:00 PM 107.86 110.86 
1239 115 133864 S 7/14/2013 6:17:00 PM 108.86 109.86 
1240 115 133864 B 7/14/2013 6:12:00 PM 109.86 NULL 
1241 115 133864 B 7/14/2013 6:17:00 PM 110.86 NULL 

Логика врезать является:

Для каждой записи, нуждающегося для получения направления OPPOSITE и существующего TrdTime> Другие записи TrdTime. Например: для ключа 1237, направление S и TrdTime - 7/15/2013 6:18:00 PM. Для этой записи записаны следующие записи: 1240 и 1241, имеющие противоположную сторону 'B' и существующую запись TrdTime> эти две записи. Но TrdTime из 1241 выбирается, так как он упорядочен по самому близкому и наивысшему времени TrdTime.

Как реализовать эту функциональность.

Я думал об этом, используя функцию LEAD и раздел.

Я не могу использовать курсоры, так как таблицы не индексируются и записи более 5 млн. Записей. Я не хочу самостоятельно присоединяться к сикне, это очень трудоемко.

Любые предложения, пожалуйста.

+0

Как закончилась запись с 'trdtime = 7/14/2013 6:12:00 PM' между двумя записями с' trdtime = 7/14/2013 6: 17: 00'? Должна ли запись с 'trdtime = 7/14/2013 6:12:00 PM' последней, согласно« упорядоченному ближайшим и самым высоким TrdTime »? Или есть другое правило заказа, которое вы не упомянули? –

+0

Дополнительных заказов нет. Запись с trdtime = 7/14/2013 6:12:00 PM может прийти в конце. Игнорируйте заказ. – cormalado

ответ

1

В качестве одного из подходов, мы можем сделать следующее:

with cte(key, book, prd_key, direction, trdtime, price, grp) as(
    select t.* 
     , dense_rank() over(order by t.trdtime desc) 
    from trd t 
) 
select q.key 
    , q.book 
    , q.prd_key 
    , q.direction 
    , q.trdtime 
    , q.price 
    , grp 
    , (select max(c.price) 
      from cte c 
      where q.direction <> c.direction 
      and c.grp = (select min(grp) 
          from cte l 
         where l.direction <> q.direction 
          and l.grp > q.grp 
         ) 
     ) as next_price 
    from cte q 

Результат:

Key Book Prd_Key Direction Trdtime    Price Next_Price 
---------------------------------------------------------------------------- 
1234 115 133864 B   17.07.13 6:18:00 PM 108,859 108,866 
1235 115 133864 S   17.07.13 6:18:00 PM 108,859 108,872 
1245 115 133864 S   17.07.13 6:18:00 PM 108,859 108,872 
1236 115 133864 B   15.07.13 6:18:00 PM 108,872 107,86 
1237 115 133864 S   15.07.13 6:18:00 PM 108,866 110,86 
1247 115 133864 S   15.07.13 6:18:00 PM 108,866 110,86 
1238 115 133864 S   14.07.13 6:18:00 PM 107,86 110,86 
1239 115 133864 S   14.07.13 6:17:00 PM 108,86 109,86 
1241 115 133864 B   14.07.13 6:17:00 PM 110,86 null 
1240 115 133864 B   14.07.13 6:12:00 PM 109,86 null 

SQLFiddle Demo

записей делится на группы, используя dens_rank() аналитическую функцию:

select t.* 
     , dense_rank() over(order by t.trdtime desc) 
    from trd t 

Результат:

Key Book Prd_Key Direction Trdtime    Price Next_Price grp 
---------------------------------------------------------------------------- 
1234 115 133864 B   17.07.13 6:18:00 PM 108,859 108,866  1 
1235 115 133864 S   17.07.13 6:18:00 PM 108,859 108,872  1 
1245 115 133864 S   17.07.13 6:18:00 PM 108,859 108,872  1 
1236 115 133864 B   15.07.13 6:18:00 PM 108,872 107,86  2 
1237 115 133864 S   15.07.13 6:18:00 PM 108,866 110,86  2 
1247 115 133864 S   15.07.13 6:18:00 PM 108,866 110,86  2 
1238 115 133864 S   14.07.13 6:18:00 PM 107,86 110,86  3 
1239 115 133864 S   14.07.13 6:17:00 PM 108,86 109,86  4 
1241 115 133864 B   14.07.13 6:17:00 PM 110,86 null  4 
1240 115 133864 B   14.07.13 6:12:00 PM 109,86 null  5 

Затем мы выбираем Next_price, как max(price) из ближайшей группы, которые включают в противоположное направление.

+0

Невероятно, что вы можете сделать с sql, да? :) Хотя лично для ремонтопригодности я, вероятно, использовал бы pl/sql для чего-то такого сложного. ;) О да, может быть, вам следует объяснить, что, используя с, вы фактически только запрашиваете таблицу «trd» один раз. – winkbrace

Смежные вопросы