PL/SQL Split, separate a date into new dates according to black out dates!

前端 未结 2 1113
没有蜡笔的小新
没有蜡笔的小新 2021-02-10 12:23

I have lets say a \"travel date\" and black out dates. I will split the travel date into pieces according to the black out dates.

Note: Travel Date can be between

2条回答
  •  后悔当初
    2021-02-10 12:53

    This returns a discrete list of all dates that exist in the Travel Dates range but not in the Blackout Dates list, and then combines them using Oracle - Convert value from rows into ranges:

    WITH traveldate AS
      (SELECT TO_DATE('2011 01 04','YYYY MM DD') AS start_date
             ,TO_DATE('2011 12 11','YYYY MM DD') AS end_date FROM DUAL)
        ,blackout AS
      (SELECT TO_DATE('2010 11 01','YYYY MM DD') AS start_date
             ,TO_DATE('2011 02 11','YYYY MM DD') AS end_date FROM DUAL
       UNION ALL
       SELECT TO_DATE('2011 01 20','YYYY MM DD') AS start_date
             ,TO_DATE('2011 02 15','YYYY MM DD') AS end_date FROM DUAL
       UNION ALL
       SELECT TO_DATE('2011 03 13','YYYY MM DD') AS start_date
             ,TO_DATE('2011 04 10','YYYY MM DD') AS end_date FROM DUAL
       UNION ALL
       SELECT TO_DATE('2011 03 20','YYYY MM DD') AS start_date
             ,TO_DATE('2011 06 29','YYYY MM DD') AS end_date FROM DUAL)
        ,days AS
      (SELECT TO_DATE('2010 01 01','YYYY MM DD') + ROWNUM d
       FROM DUAL CONNECT BY LEVEL <= 1000)
        ,base AS
      (SELECT d AS n
       FROM   days, traveldate
       WHERE  d >= traveldate.start_date AND d <= traveldate.end_date
       MINUS
       SELECT d AS n
       FROM   days, blackout
       WHERE  d >= blackout.start_date AND d <= blackout.end_date
      )
    ,lagged AS
    (
        SELECT n, LAG(n) OVER (ORDER BY n) lag_n FROM base
    )
    , groups AS
    (
        SELECT n, row_number() OVER (ORDER BY n) groupnum
          FROM lagged
          WHERE lag_n IS NULL OR lag_n < n-1
    )
    , grouped AS
    (
        SELECT n, (SELECT MAX(groupnum) FROM groups
                     WHERE groups.n <= base.n
                  ) groupnum
          FROM base
    )
    SELECT groupnum, MIN(n), MAX(n)
      FROM grouped
      GROUP BY groupnum
      ORDER BY groupnum;
    

    Result:

    GROUPNUM    MIN(N)          MAX(N)
    
    1           16/02/2011  12/03/2011
    2           30/06/2011  11/12/2011
    

提交回复
热议问题