如何组合连续的数字范围

Tho*_*ner 5 sql oracle

我正在寻找一种在单个select语句中组合连续数字范围的简洁方法.

说我的表有这些记录:

first_number    last_number
0   9
10  19
20  29
40  49
50  59
70  79
Run Code Online (Sandbox Code Playgroud)

然后输出如下:

first_number    last_number
0   29
40  59
70  79
Run Code Online (Sandbox Code Playgroud)

这就是我想出来的:

select first_number, last_number_of_range
from
(
  select 
    first_number, is_continuing, is_continued,
    nvl(lead (last_number,1,null) over (order by first_number), last_number) as last_number_of_range
  from
  (
    select *
    from
    (
      select first_number, last_number, 
       case when lag (last_number,1,null) over (order by first_number) + 1 = first_number then 1 else 0 end as is_continuing, 
       case when lead (first_number,1,null) over (order by last_number) - 1 = last_number then 1 else 0 end as is_continued
      from 
      (
        select 0 as first_number, 9 as last_number from dual
        union all
        select 10 as first_number, 19 as last_number from dual
        union all
        select 20 as first_number, 29 as last_number from dual
        union all
        select 40 as first_number, 49 as last_number from dual
        union all
        select 50 as first_number, 59 as last_number from dual
        union all
        select 70 as first_number, 79 as last_number from dual
      )
    )
    where is_continuing = 0 or is_continued = 0 -- remove all but first and last of consecutive records
  )
)
where is_continuing = 0 -- now at last remove those records that gave us the last_number_of_range
;
Run Code Online (Sandbox Code Playgroud)

这很好用.只是,对于如此小的任务来说,它看起来如此复杂.我很想知道还有比我更直接的方式.

Tec*_*hDo 2

请尝试:

with T1 as (
  select 
    row_number() over (order by first_number) RNum, 
    first_number, 
    last_number 
  From yourtable
)
,T (RNUM, first_number, last_number, CNT) as (
    select T1.*, 1 CNT from T1 where RNum=1
    union all
    SELECT b.RNUM, b.first_number, b.last_number, (case when b.first_number=T.last_number+1 then t.CNT 
                        else T.CNT+1 end) CNT
    from T1 b INNER JOIN T on b.RNum=T.RNum+1
)
select 
   min(first_number) as first_number,
    max(last_number) as last_number
From T group by T.CNT
Run Code Online (Sandbox Code Playgroud)

SQL 小提琴演示