print start and end date in one row for continous or overlaping date ranges in oracle SQL

前端 未结 2 597
逝去的感伤
逝去的感伤 2021-01-22 17:13

I would like to print in one row start date and end date for continous or overlaping date ranges.

here is the data

create table orders (
po varchar2(6),
st         


        
相关标签:
2条回答
  • 2021-01-22 17:43

    Use window functions to see if there is any overlap with previous records. Then a cumulative sum to assign a "grouping" and aggregate.

    I like to use a cumulative max for more generic overlaps:

    select po, min(startdate), max(enddate)
    from (select o.*,
                 sum(case when prev_enddate >= startdate then 0 else 1 end) over (partition by po order by startdate) as grouping
          from (select o.*,
                       max(enddate) over (partition by po order by startdate range between unbounded preceding and '1' second preceding) as prev_enddate
                from orders o
               ) o
         ) o
    group by po, grouping;
    

    In many cases, you can use lag() instead of max():

    select po, min(startdate), max(enddate)
    from (select o.*,
                 sum(case when prev_enddate >= startdate then 0 else 1 end) over (partition by po order by startdate) as grouping
          from (select o.*,
                       lag(enddate) over (partition by po order by startdate) as prev_enddate
                from orders o
               ) o
         ) o
    group by po, grouping;
    

    This works so long as the previous row has the overlap, which is typically the case.

    0 讨论(0)
  • 2021-01-22 17:48

    There is an elegant (and efficient) solution using the match_recognize clause (which requires Oracle 12.1 or higher).

    select po, startdate, enddate
    from   orders
    match_recognize (
      partition by po
      order     by startdate
      measures  first(startdate) as startdate, max(enddate) as enddate
      pattern   ( c* n )
      define    c as max(enddate) + 1 >= next(startdate)  
    );
    
    0 讨论(0)
提交回复
热议问题