在连续的日期范围内计算/得出第一个开始日期

问题描述

我使用的是Postgres,我正在努力思考如何精确地得出连续日期范围内的第一个开始日期。例如:-

ID | Start Date | End Date
==========================
1|2020-01-01|2020-01-31
1|2020-02-01|2020-03-31
1|2020-05-01|2020-06-30
1|2020-07-01|2020-07-31
1|2020-08-01|2020-08-31

我期望的输出

ID | Start Date | End Date | Continous Date
===========================================
1|2020-01-01|2020-01-31|2020-01-01
1|2020-02-01|2020-03-31|2020-01-01
1|2020-05-01|2020-06-30|2020-05-01
1|2020-07-01|2020-07-31|2020-05-01
1|2020-08-01|2020-08-31|2020-05-01

基本上,它应该给我连续的日期范围的第一个开始日期。

感谢您对我如何解决此问题的意见或指示。不幸的是,CTE是我可能无法接受的。

解决方法

这是一个空白和孤岛问题,其中孤岛被定义为一组具有连续日期的连续记录。您想要每个岛屿的起点。

这是一种使用lag()来检索“上一个”结束日期的方法,然后使用累积的sum()构建组,该组在每个间隔上都递增。

select t.*,min(start_date) over(partition by id,grp order by start_date) continous_date
from (
    select t.*,count(*) filter(where start_date is distinct from lag_end_date + interval '1 day') over(partiton by id order by start_date) grp
    from (
        select t.*,lag(end_date) over(partition by id order by start_date) lag_end_date
        from mytable t
    ) t
) t
,

这是一个空白问题。基本上,使用lag()或其他函数确定重叠的位置。然后,通过非重叠的累积和来识别“岛屿”。我会这样处理:

select t.*,min(start_date) over (partition by id,grp) as continuous_start_date
from (select t.*,count(*) filter (where prev_end_date is null or prev_end_date < start_date - interval '1 day') as grp
      from (select t.*,max(end_date) over (partition by id order by start_date rows between unbounded preceding and 1 preceding) as prev_end_date
            from t
           ) t
     ) t;

请注意,这会处理相邻记录之间以及从前一天开始的重叠记录。