调整组内的日期重叠

rjee0c15  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(365)

我有这个表,我想调整结束日期前一天的下一个st\ U日期的情况下,如果有重叠的日期为一组id

TABLE HAVE

ID   ST_DATE         END_DATE
1   2020-01-01     2020-02-01
1   2020-05-10     2020-05-20
1   2020-05-18     2020-06-19
1   2020-11-11     2020-12-01  
2   1999-03-09     1999-05-10
2   1999-04-09     2000-05-10
3   1999-04-09     2000-05-10
3   2000-06-09     2000-08-16
3   2000-08-17     2009-02-17

下面是我要找的

TABLE WANT

ID   ST_DATE         END_DATE
1   2020-01-01     2020-02-01
1   2020-05-10     2020-05-17  =====changed to a day less than the next ST_DATE due to some sort of overlap
1   2020-05-18     2020-06-19
1   2020-11-11     2020-12-01  
2   1999-03-09     1999-04-08 =====changed to a day less than the next ST_DATE due to some sort of overlap
2   1999-04-09     2000-05-10
3   1999-04-09     2000-05-10
3   2000-06-09     2000-08-16
3   2000-08-17     2009-02-17
cwtwac6a

cwtwac6a1#

也许你可以用lead()来做这个。最初的想法:

select 
  id, st_date, end_date
, lead( st_date ) over ( partition by id order by st_date ) nextstart_
from overlap
;

-- result
        ID ST_DATE   END_DATE  NEXTSTART
---------- --------- --------- ---------
         1 01-JAN-20 01-FEB-20 10-MAY-20
         1 10-MAY-20 20-MAY-20 18-MAY-20
         1 18-MAY-20 19-JUN-20 11-NOV-20
         1 11-NOV-20 01-DEC-20          
         2 09-MAR-99 10-MAY-99 09-APR-99
         2 09-APR-99 10-MAY-00          
         3 09-APR-99 10-MAY-00 09-JUN-00
         3 09-JUN-00 16-AUG-00 17-AUG-00
         3 17-AUG-00 17-FEB-09

一旦你有了下一个开始日期和结束日期并排(原来是这样),你就可以使用case。。。根据需要调整日期。

select ilv.id, ilv.st_date
, case 
    when ilv.end_date > ilv.nextstart_ then
      to_char( ilv.nextstart_ - 1 ) || ' <- modified end date'
    else
      to_char( ilv.end_date )
  end dt_modified
from (
  select 
    id, st_date, end_date
  , lead( st_date ) over ( partition by id order by st_date ) nextstart_
  from overlap
) ilv
;

        ID ST_DATE   DT_MODIFIED                            
---------- --------- ---------------------------------------
         1 01-JAN-20 01-FEB-20                              
         1 10-MAY-20 17-MAY-20 <- modified end date         
         1 18-MAY-20 19-JUN-20                              
         1 11-NOV-20 01-DEC-20                              
         2 09-MAR-99 08-APR-99 <- modified end date         
         2 09-APR-99 10-MAY-00                              
         3 09-APR-99 10-MAY-00                              
         3 09-JUN-00 16-AUG-00                              
         3 17-AUG-00 17-FEB-09

在这儿摆弄。

k5ifujac

k5ifujac2#

如果两个“窗口”相同 id 如果开始日期相同,那么问题就没有意义了。所以,让我们假设这个问题是有意义的-也就是说,组合 (id, st_date) 是唯一的输入。
然后,问题可以表述如下:对于每个 id ,按行排序 st_date 提升。那么,对于每一行,如果 end_dt 小于以下值 st_date ,按原样返回行。否则更换 end_dt 以下是 st_date ,减1。最后一步可以通过分析 lead() 功能。
解决方案可能如下所示:

select id, st_date,
       least(end_date, lead(st_date, 1, end_date + 1) 
                       over (partition by id order by st_date) - 1) as end_date
from   have
;

关于 end_date + 1lead 函数处理每个 id . 对于这样的行,没有“next”行,因此 lead 会回来的 null . 可以使用函数的第三个参数覆盖默认值。

相关问题