我在oracle数据库中有如下示例数据:
set_no set_eff_dt set_term_dt
1000 1/1/2015 12/31/2016
1000 1/1/2017 10/31/2017
1000 11/1/2017 12/31/2018
1000 2/1/2019 10/31/2019
1000 11/1/2019 10/31/2020
我想要像下面一样的输出
1000 1/1/2015 12/31/2018
1000 2/1/2019 10/31/2020
让我解释一下模式和输出将如何实现
在第二行中,set_off_dt
是set_term_dt +1
的结果
第三行set_off_dt
是第二行的set_term_dt +1
的结果
在第四行中,set_eff_dt
不是来自第三行的set_term_dt+1
的结果,因此这里是分组中断可能是
在第5行中,set_eff_dt
再次是来自第4行的set_term_dt+1
的结果因此它将被折叠为第4行,如输出所示
在同样的模式中,我们有数千条记录,我们希望按照描述的逻辑进行折叠
what i have tried
SELECT SET_NO,SET_EFF_DT,
case when LEAD (SET_EFF_DT,1) OVER (ORDER BY SET_EFF_DT)-1 = set_trm_dt then 1 else 0 end flg
FROM xx_fl_test
如果新行中的SET_EFF_DT
=set_trm_dt
,我只能识别标志。。。但我仍然不明白如何处理这些数据。
这是一个缺口和孤岛问题。我将通过以下步骤计算分组变量来解决问题:
- 确定组的起始位置。为此,我在之前的
set_trm_dt
和case
逻辑上做了一个滞后,看看是否没有"连接"> - 对标志进行累积求和,为每一行分配一个
grp
- 按
grp
聚合
代码如下:
select set_no, min(set_eff_dt), max(set_trm_dt)
from (select t.*,
sum(case when set_eff_dt > prev_set_trm_dt + 1 then 1 else 0 end) over (partition by set_no order by set_eff_dt) as grp
from (select t.*,
lag(set_trm_dt) over (partition by set_no order by set_eff_dt) as prev_set_trm_dt
from xx_fl_test t
) t
) t
group by set_no, grp;
考虑对生成的列进行累积求和,以生成需要两个CTE的分组变量:一个用于flg计算,另一个用于带有窗口函数的flg的累积求和。最后,通过cum_flg进行聚合(但有条件地为从1开始的第一个分组值加1(。
WITH sub AS
(SELECT SET_NO, SET_EFF_DT, SET_TRM_DT,
CASE WHEN LEAD (SET_EFF_DT,1) OVER (ORDER BY SET_EFF_DT)-1 = SET_TRM_DT
THEN 1
ELSE 0
END AS flg
FROM xx_fl_test),
calc AS
(SELECT SET_NO, SET_EFF_DT, SET_TRM_DT,
SUM (flg) OVER (PARTITION BY SET_NO ORDER BY SET_EFF_DT) AS cum_flg
FROM sub)
SELECT SET_NO,
MIN(SET_EFF_DT) AS MIN_SET_EFF_DT,
MAX(SET_TRM_DT) AS MAX_SET_TRM_DT
FROM calc
GROUP BY SET_NO,
CASE cum_flg
WHEN 1
THEN cum_flg + 1
END
Rextester演示