首页 > 解决方案 > SQL 连续间隔

问题描述

我在一张表中混合了间隔,需要连续间隔。具有分析功能的东西,如铅和腿?

不能使用 Pl/Sql。

ID | BEGIN| END
1  | 1    | 2
2  | 1    | 3
3  | 2    | 4
4  | 3    | 5
5  | 4    | 9
6  | 5    | 9

预期的选择结果:

ID | BEGIN| END
1  | 1    | 2
2  | 2    | 3
3  | 3    | 4
4  | 4    | 5
5  | 5    | 9

感谢帮助。

标签: sqloracleintervals

解决方案


如果您使用的是实际支持的 oracle 版本,您可以使用lateralcross apply

--your test data:
with t(ID, BEGIN, END) as (
select 1, 1, 2 from dual union all
select 2, 1, 3 from dual union all
select 3, 2, 4 from dual union all
select 4, 3, 5 from dual union all
select 5, 4, 9 from dual union all
select 6, 5, 9 from dual
)-- end of your test data
--main query:
select 
  distinct t.id,t.begin,t.end,v.begin2,v.end2
from t
    ,lateral(select t.begin+level-1 as begin2
                  , t.begin+level as end2
             from dual
             connect by t.begin+level<=t.end)
             v
order by t.id,t.begin,t.end,v.begin2,v.end2;

结果:

        ID      BEGIN        END     BEGIN2       END2
---------- ---------- ---------- ---------- ----------
         1          1          2          1          2
         2          1          3          1          2
         2          1          3          2          3
         3          2          4          2          3
         3          2          4          3          4
         4          3          5          3          4
         4          3          5          4          5
         5          4          9          4          5
         5          4          9          5          6
         5          4          9          6          7
         5          4          9          7          8
         5          4          9          8          9
         6          5          9          5          6
         6          5          9          6          7
         6          5          9          7          8
         6          5          9          8          9

16 rows selected.

如您所见,我们只是在其中生成行lateral并计算新的 begin2 和 end2。我添加了原始内容beginend只是为了使其更具可读性。显然我们可以省略它们:

select 
  distinct t.id,v.begin2,v.end2
from t
    ,lateral(select t.begin+level-1 as begin2
                  , t.begin+level as end2
             from dual
             connect by t.begin+level<=t.end)
             v
order by t.id,v.begin2,v.end2;

推荐阅读