SQL DateDiff advanced usage?

前端 未结 6 1526
慢半拍i
慢半拍i 2020-12-19 19:26

I need to calculate the DateDiff (hours) between two dates, but only during business-hours (8:30 - 16:00, no weekends). This result will then be put into the Reaction_Time c

6条回答
  •  执念已碎
    2020-12-19 19:39

    DECLARE @BusHourStart DATETIME, @BusHourEnd DATETIME
    SELECT @BusHourStart = '08:30:00', @BusHourEnd = '16:00:00'
    DECLARE @BusMinutesStart INT, @BusMinutesEnd INT
    SELECT @BusMinutesStart = DATEPART(minute,@BusHourStart)+DATEPART(hour,@BusHourStart)*60, 
    @BusMinutesEnd = DATEPART(minute,@BusHourEnd)+DATEPART(hour,@BusHourEnd)*60 
    DECLARE @Dates2 TABLE (ID INT, DateStart DATETIME, DateEnd DATETIME)
    INSERT INTO @Dates2
    SELECT 1, '15:00:00 04/29/2003', '11:00:00 04/30/2003' UNION
    SELECT 2, '14:00:00 04/30/2003', '14:00:00 05/01/2003' UNION
    SELECT 3, '14:00:00 05/02/2003', '14:00:00 05/06/2003' UNION
    SELECT 4, '14:00:00 05/02/2003', '14:00:00 05/04/2003' UNION
    SELECT 5, '07:00:00 05/02/2003', '14:00:00 05/02/2003' UNION
    SELECT 6, '14:00:00 05/02/2003', '23:00:00 05/02/2003' UNION
    SELECT 7, '07:00:00 05/02/2003', '08:00:00 05/02/2003' UNION
    SELECT 8, '22:00:00 05/02/2003', '23:00:00 05/03/2003' UNION
    SELECT 9, '08:00:00 05/03/2003', '23:00:00 05/04/2003' UNION
    SELECT 10, '07:00:00 05/02/2003', '23:00:00 05/02/2003' 
    
    -- SET DATEFIRST to U.S. English default value of 7.
    SET DATEFIRST 7
    
    SELECT ID, DateStart, DateEnd, CONVERT(VARCHAR, Minutes/60) +':'+ CONVERT(VARCHAR, Minutes % 60) AS ReactionTime
    FROM ( 
        SELECT ID, DateStart, DateEnd, Overtime,
            CASE 
                WHEN DayDiff = 0 THEN 
                    CASE 
                        WHEN (MinutesEnd - MinutesStart - Overtime) > 0 THEN (MinutesEnd - MinutesStart - Overtime) 
                        ELSE 0 
                        END
                WHEN DayDiff > 0  THEN 
                    CASE 
                        WHEN (StartPart + EndPart - Overtime) > 0 THEN (StartPart + EndPart - Overtime) 
                        ELSE 0 
                        END + DayPart
                ELSE 0
            END AS Minutes 
        FROM(
            SELECT ID, DateStart, DateEnd, DayDiff, MinutesStart, MinutesEnd,
                    CASE WHEN(@BusMinutesStart - MinutesStart) > 0 THEN (@BusMinutesStart - MinutesStart) ELSE 0 END +
                    CASE WHEN(MinutesEnd - @BusMinutesEnd) > 0 THEN (MinutesEnd - @BusMinutesEnd) ELSE 0 END AS Overtime, 
                    CASE WHEN(@BusMinutesEnd - MinutesStart) > 0 THEN (@BusMinutesEnd - MinutesStart) ELSE 0 END AS StartPart,
                    CASE WHEN(MinutesEnd - @BusMinutesStart) > 0 THEN (MinutesEnd - @BusMinutesStart) ELSE 0 END AS EndPart,
                    CASE WHEN DayDiff > 1 THEN (@BusMinutesEnd - @BusMinutesStart)*(DayDiff - 1) ELSE 0 END AS DayPart
            FROM (
                    SELECT DATEDIFF(d,DateStart, DateEnd) AS DayDiff, ID, DateStart, DateEnd,  
                    DATEPART(minute,DateStart)+DATEPART(hour,DateStart)*60 AS MinutesStart,
                    DATEPART(minute,DateEnd)+DATEPART(hour,DateEnd)*60 AS MinutesEnd 
                    FROM (
                            SELECT ID,
                                    CASE 
                                            WHEN DATEPART(dw, DateStart) = 7 
                                            THEN DATEADD(SECOND, 1, DATEADD(DAY, DATEDIFF(DAY, 0, DateStart), 2))
                                            WHEN DATEPART(dw, DateStart) = 1 
                                            THEN DATEADD(SECOND, 1, DATEADD(DAY, DATEDIFF(DAY, 0, DateStart), 1))
                                    ELSE DateStart END AS DateStart,
                                    CASE 
                                            WHEN DATEPART(dw, DateEnd) = 7 
                                            THEN DATEADD(SECOND, -1, DATEADD(DAY, DATEDIFF(DAY, 0, DateEnd), 0))
                                            WHEN DATEPART(dw, DateEnd) = 1 
                                            THEN DATEADD(SECOND, -1, DATEADD(DAY, DATEDIFF(DAY, 0, DateEnd), -1))
                                    ELSE DateEnd END AS DateEnd FROM @Dates2
                    )Weekends
            )InMinutes
        )Overtime
    )Calculation
    

提交回复
热议问题