SQL: Merge Date Ranges

后端 未结 3 484
星月不相逢
星月不相逢 2020-12-06 02:59

I\'ve a table, which describes work slices of a business working calendar: (date format is 24 hours format)

PK  | STARTDATE          | ENDDATE
______________         


        
3条回答
  •  离开以前
    2020-12-06 03:18

    This is my solution.

    IF OBJECT_ID('tempdb..#tblDates') IS NOT NULL
        DROP TABLE #tblDates
    
    CREATE TABLE #tblDates (AutoId INT IDENTITY, StartDate DATE, EndDate DATE)
    
    INSERT #tblDates (StartDate, EndDate) SELECT '2014-11-02', '2014-11-08'
    INSERT #tblDates (StartDate, EndDate) SELECT '2014-11-07', '2014-11-10'
    INSERT #tblDates (StartDate, EndDate) SELECT '2014-11-06', '2014-11-12'
    
    INSERT #tblDates (StartDate, EndDate) SELECT '2014-11-02', '2014-11-15'
    
    INSERT #tblDates (StartDate, EndDate) SELECT '2014-12-10', '2014-12-13'
    INSERT #tblDates (StartDate, EndDate) SELECT '2014-12-12', '2014-12-15'
    INSERT #tblDates (StartDate, EndDate) SELECT '2014-12-14', '2014-12-16'
    
    
    -- Optional / Remove the duplicated records of same StartDate and EndDate
    DELETE FROM #tblDates WHERE AutoId NOT IN (SELECT MAX(AutoId) FROM #tblDates GROUP BY StartDate, EndDate)
    
    -- Optional / Get only the record with max EndDate grouped by StartDate, Remove Others
    DELETE  d1
    FROM    #tblDates d1
            JOIN (SELECT x.StartDate, MAX(x.EndDate) MAXEndDate FROM #tblDates x GROUP BY x.StartDate) d2 ON d2.StartDate = d1.StartDate AND d2.MAXEndDate != d1.EndDate
    
    -- Optional / Get only the record with min StartDate grouped by EndDate, Remove Others
    DELETE  d1
    FROM    #tblDates d1
            JOIN (SELECT x.EndDate, MIN(x.StartDate) MINStartDate FROM #tblDates x GROUP BY x.EndDate) d2 ON d2.EndDate = d1.EndDate AND d2.MINStartDate != d1.StartDate
    
    -- Optional / Remove the overlapping ranges of relevant StartDate and EndDate
    DELETE  c
    FROM    #tblDates p
            JOIN #tblDates c ON c.AutoId != p.AutoId AND c.StartDate BETWEEN p.StartDate AND p.EndDate AND c.EndDate BETWEEN p.StartDate AND p.EndDate
    
    
    ;WITH Ranges
    AS
    (
        SELECT  s.StartDate, s.EndDate
        FROM    #tblDates s
                LEFT JOIN #tblDates a ON a.AutoId != s.AutoId AND s.StartDate BETWEEN a.StartDate AND a.EndDate AND s.StartDate != a.StartDate
        WHERE   a.AutoId IS NULL
        UNION ALL
        SELECT  r.StartDate, d.EndDate
        FROM    Ranges r
                JOIN #tblDates d ON r.EndDate != d.EndDate AND r.EndDate BETWEEN d.StartDate AND d.EndDate
    )
    
    SELECT StartDate, MAX(EndDate) EndDate FROM Ranges GROUP BY StartDate
    

提交回复
热议问题