ROW_NUMBER 查询
ROW_NUMBER query
我有一个 table:
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)
None个都会满足我要的条件。有没有办法查询这个?
select *, dense_rank() over(partition by trip, stop order by time) as sqnc
from yourtable;
使用 dense_rank
这样您就可以连续获取所有数字,中间没有跳过的数字。
我认为这比简单的 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;
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
您想查看停靠点是否在一行和下一行之间发生变化。如果是这样,您想增加序列。因此,使用滞后将上一个停止点放入当前行。
我使用 DECODE 是因为它处理 NULL 的方式比 CASE 更简洁,但如果您按照教科书学习,您可能应该使用 CASE。
将 SUM 用作带有 ORDER BY 子句的分析函数将给出您正在寻找的答案。
我有一个 table:
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)
None个都会满足我要的条件。有没有办法查询这个?
select *, dense_rank() over(partition by trip, stop order by time) as sqnc
from yourtable;
使用 dense_rank
这样您就可以连续获取所有数字,中间没有跳过的数字。
我认为这比简单的 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;
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
您想查看停靠点是否在一行和下一行之间发生变化。如果是这样,您想增加序列。因此,使用滞后将上一个停止点放入当前行。
我使用 DECODE 是因为它处理 NULL 的方式比 CASE 更简洁,但如果您按照教科书学习,您可能应该使用 CASE。
将 SUM 用作带有 ORDER BY 子句的分析函数将给出您正在寻找的答案。