Oracle根据序列聚合特定组

时间:2017-10-25 08:36:43

标签: sql oracle oracle11g

我有一张桌子T:

Entity  type  starttime    sequence  duration
1       A     2017010101   1         12
1       A     2017010102   2         11
1       A     2017010103   3         3
1       A     2017010104   4         1
1       A     2017010105   1         19
1       A     2017010106   2         18
2       A     2017010101   1         18
2       A     2017010102   1         100
3       A     2017010101   1         120

我需要聚合数据,以便每次序列运行都有一个总持续时间和第一个启动时间:

Entity  type  starttime    sequence  duration
1       A     2017010101   1         27
1       A     2017010105   1         37
2       A     2017010101   1         18
2       A     2017010102   1         100
3       A     2017010101   1         120

我认为这是一个缺口和岛屿问题,但我无法弄明白......

我曾尝试使用lead() over (partition by entity order by sequence)但这会继续抓住下一轮序列。

2 个答案:

答案 0 :(得分:2)

如果sequence没有间隙,那么您可以使用row_number()并减去序列来创建用于聚合的临时列grp

select entity, type, min(starttime) starttime, 
       min(sequence) sequence, sum(duration) duration
  from (select t.*, 
               row_number() over (partition by entity order by starttime) - sequence grp 
          from t)
  group by entity, type, grp
  order by entity, grp

测试:

with t(entity, type, starttime, sequence, duration) as (
    select 1, 'A', 2017010101, 1,  12 from dual union all
    select 1, 'A', 2017010102, 2,  11 from dual union all
    select 1, 'A', 2017010103, 3,   3 from dual union all
    select 1, 'A', 2017010104, 4,   1 from dual union all
    select 1, 'A', 2017010105, 1,  19 from dual union all
    select 1, 'A', 2017010106, 2,  18 from dual union all
    select 2, 'A', 2017010101, 1,  18 from dual union all
    select 2, 'A', 2017010102, 1, 100 from dual union all
    select 3, 'A', 2017010101, 1, 120 from dual )
select entity, type, min(starttime) starttime, 
       min(sequence) sequence, sum(duration) duration
  from (select t.*, 
               row_number() over (partition by entity order by starttime) - sequence grp 
          from t)
  group by entity, type, grp
  order by entity, grp



    ENTITY TYPE  STARTTIME   SEQUENCE   DURATION
---------- ---- ---------- ---------- ----------
         1 A    2017010101          1         27
         1 A    2017010105          1         37
         2 A    2017010101          1         18
         2 A    2017010102          1        100
         3 A    2017010101          1        120

答案 1 :(得分:0)

您不需要row_number()。您可以从starttime中减去序列 - 假设starttime是日期。每组连续值的差异是恒定的:

select entity, type, min(starttime) as starttime, 
       min(sequence) as sequence, sum(duration) as duration
from t
group by entity, type, (starttime - sequence)
order by entity, grp;

如果starttime是一个字符串,那么您需要{Ponder建议的row_number()。如果starttime是一个数字,那么这可以在一个月内完成,但您可能需要row_number()