使用Oracle中的Lead进行分区

时间:2013-08-28 13:43:45

标签: oracle analytic-functions lead partition

我遇到了用分区实现LEAD / LAG的问题。

以下是示例和预期结果

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>这两个记录。 但是选择了1241的TrdTime,因为它是按最近和最高的TrdTime排序的。

我如何实现此功能。

我正在考虑使用LEAD功能和分区。

我不能使用游标,因为表没有索引,并且有超过5密耳的记录。 我不想自己加入sicne,这是非常耗时的。

请提出任何建议。

1 个答案:

答案 0 :(得分: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),其中包括相反的方向。