简体   繁体   中英

SQL to find start and end date for an ID

I have a table with ID, start_date and end_date columns.

Table:

ID    start_date    end_date
1     01/01/2017    01/01/2018
1     01/01/2018    01/01/2019
1     01/01/2019    01/01/2020
2     01/01/2016    01/01/2017
2     01/01/2017    01/01/2018
2     01/01/2019    01/01/2020

I want to write a query to get the following output:

Output:

ID    start_date    end_date
1     01/01/2017    01/01/2020
2     01/01/2016    01/01/2018
2     01/01/2019    01/01/2020

This is a form of gaps and islands.

My recommendation in this case is to use a cumulative max to see if there are any overlaps with preceding rows and use that to determine where an "island" starts. Then, use a cumulative sum to define the islands and aggregation:

select id, min(start_date), max(end_date
from (select t.*,
             sum(case when prev_end_date >= start_date then 0 else 1 end) over (partition by id order by start_date) as grp
      from (select t.*,
                   lag(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
group by id, grp;

You can do a cumulative sum to solve this variation of the gaps-and-island problem:

select 
    id,
    min(start_date) start_date,
    max(end_date) end_date
from (
    select 
        t.*,
        sum(case when start_date = lag_end_date then 0 else 1 end) 
            over(partition 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
group by id, grp
order by id, grp

Demo on DB Fiddle :

ID | START_DATE | END_DATE  
-: | :--------- | :---------
 1 | 01/01/2017 | 01/01/2020
 2 | 01/01/2016 | 01/01/2018
 2 | 01/01/2019 | 01/01/2020
     Select id, Min(startdate), Max(case 
          when 
           lag(enddate) 
         over
    (partition by id order by id) =startdate
       then 
       Enddate end) from table group by
       id;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM