【问题标题】:ROW_NUMBER queryROW_NUMBER 个查询
【发布时间】:2015-10-26 23:16:10
【问题描述】:

我有一张桌子:

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)

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

【问题讨论】:

  • 这是给sql-server 的吗?或者这是为了什么其他 RDBMS?请添加相关标签!
  • Oracle SQL 对不起,我尝试添加免费标签,但我的级别不能

标签: sql oracle window-functions


【解决方案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】:
    select *, dense_rank() over(partition by trip, stop order by time) as sqnc
    from yourtable;
    

    使用dense_rank,这样您就可以连续获得所有数字,中间没有跳过的数字。

    【讨论】:

    • 。 .这不符合 OP 的要求。它将标记行 1, 1, 2, 3, 1, 4, 。 . .
    【解决方案3】:

    我认为这比简单的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;
    

    【讨论】:

    • 对于 Trip =2、stop = B、time = 2.25 给出错误结果。
    猜你喜欢
    • 2018-11-16
    • 2023-03-06
    • 2013-08-09
    • 1970-01-01
    • 2023-04-09
    • 2016-06-08
    • 1970-01-01
    • 2018-08-26
    • 2018-02-27
    相关资源
    最近更新 更多