ROW_NUMBER查询

时间:2015-08-04 13:51:00

标签: sql oracle window-functions

我有一张桌子:

Trip  Stop  Time 
-----------------
1     A     1:10
1     B     1:16
1     B     1:20
1     B     1:25
1     C     1:31
1     B     1:40
2     A     2:10
2     B     2:17
2     C     2:20
2     B     2:25  

我想在查询输出中再添加一列:

Trip  Stop  Time Sequence
-------------------------
1     A     1:10   1
1     B     1:16   2 
1     B     1:20   2
1     B     1:25   2
1     C     1:31   3
1     B     1:40   4 
2     A     2:10   1
2     B     2:17   2
2     C     2:20   3
2     B     2:25   4  

硬部分是B,如果B彼此相邻,我希望它是相同的序列,如果不是,那么算作新行。

我知道

row_number over (partition by trip order by time)
row_number over (partition by trip, stop order by time)

他们都不会满足我想要的条件。有没有办法查询这个?

3 个答案:

答案 0 :(得分:1)

select *, dense_rank() over(partition by trip, stop order by time) as sqnc
from yourtable;

使用dense_rank,以便连续获得所有数字,中间没有跳过的数字。

答案 1 :(得分:1)

create table test
(trip number
,stp  varchar2(1)
,tm   varchar2(10)
,seq  number);

insert into test values (1,     'A',     '1:10',   1);
insert into test values (1,     'B',     '1:16',   2); 
insert into test values (1,     'B',     '1:20',   2);
insert into test values (1 ,    'B',     '1:25',   2);
insert into test values (1 ,    'C',     '1:31',   3);
insert into test values (1,     'B',     '1:40',   4);
insert into test values (2,     'A',     '2:10',   1);
insert into test values (2,     'B',     '2:17',   2);
insert into test values (2,     'C',     '2:20',   3);
insert into test values (2,     'B',     '2:25',   4);

select t1.*
      ,sum(decode(t1.stp,t1.prev_stp,0,1)) over (partition by trip order by tm) new_seq
from  
     (select t.*
            ,lag(stp) over (order by t.tm) prev_stp
      from   test t
      order  by tm) t1
;

  TRIP S TM                SEQ P    NEW_SEQ
------ - ---------- ---------- - ----------
     1 A 1:10                1            1
     1 B 1:16                2 A          2
     1 B 1:20                2 B          2
     1 B 1:25                2 B          2
     1 C 1:31                3 B          3
     1 B 1:40                4 C          4
     2 A 2:10                1 B          1
     2 B 2:17                2 A          2
     2 C 2:20                3 B          3
     2 B 2:25                4 C          4

 10 rows selected 

您想要查看停止在一行与下一行之间是否发生变化。如果是,则要增加序列。因此,使用lag将前一个停靠点放入当前行。

我使用了DECODE,因为它处理NULL的方式比CASE更简洁,但是如果你跟随教科书,你应该使用CASE。

使用SUM作为具有ORDER BY子句的分析函数将给出您正在寻找的答案。

答案 2 :(得分:0)

我认为这比简单row_number()更复杂。您需要识别相邻停靠点的组,然后然后枚举它们。

您可以使用行号的差异来识别组。然后,如果旅行中没有重复停留,则差异上的dense_rank()会发生您想要的事情:

select t.*,
       dense_rank() over (partition by trip order by grp, stop)
from (select t.*,
             (row_number() over (partition by trip order by time) -
              row_number() over (partition by trip, stop order by time)
             ) as grp
      from table t
     ) t;

如果有:

select t.*, dense_rank() over (partition by trip order by mintime)
from (select t.*,
             min(time) over (partition by trip, grp, stop) as mintime
      from (select t.*,
                   (row_number() over (partition by trip order by time) -
                    row_number() over (partition by trip, stop order by time)
                   ) as grp
            from table t
           ) t
     ) t;