2015-01-14 3 views
-1

В свете есть эти две даты исходя из таблицы:TSQL DATEDIFF только рабочее время

2014-12-17 14:01:03.523 - 2014-12-20 09:59:28.783 

мне нужно знать дату различий в часах, считая, что в день я могу рассчитывать часы только от 08 AM и 17:00.

Конечно, субботы и воскресенья не должны включаться.

Я попытался использовать этот код внутри select, но я получил только разницу в днях, за исключением суббот и воскресенья.

(DATEDIFF(HOUR, convert(datetime,t.EXT_DATAINS-2), convert(datetime,b.EXT_DATAINS-2)) + 1) 
    -(DATEDIFF(wk, convert(datetime,t.EXT_DATAINS-2), convert(datetime,b.EXT_DATAINS-2)) * 2) 
    -(CASE WHEN DATENAME(dw, convert(datetime,t.EXT_DATAINS-2)) = 'Sunday' THEN 1 ELSE 0 END) 
    -(CASE WHEN DATENAME(dw, convert(datetime,b.EXT_DATAINS-2)) = 'Saturday' THEN 1 ELSE 0 END) differenza 

Пример:

2014-12-17 : 3hrs 
2014-12-18 : 8hrs 
2014-12-19 : 8hrs 
2014-12-20 : 2hrs 
Tot  : 21hrs 
+1

Возможный дубликат [Расчет рабочего времени между двумя датами] (http://stackoverflow.com/questions/5274208/calculate-business-hours-between-two-dates) – Dan

+1

Нет стандартной функции, которая поможет вам в этом. В дополнение к определению ваших «рабочих часов» (время обеденного перерыва?) И графика отпуска, вы должны определить, что произойдет, когда диапазон начинается или заканчивается вне рабочего времени. Например: если он идет от 3PM - 6PM, сколько часов? Как насчет 3AM - 10PM? –

+0

Что вы хотите в результате разницы между этими двумя датами? –

ответ

1

Используйте Recursive CTE, чтобы получить все часы с датами.

МЕТОД 1: Получить все даты с часами между FromDate и Todate

DECLARE @FROMDATE DATETIME='2014-12-17 14:01:03.523' 
DECLARE @TODATE DATETIME='2014-12-20 09:59:28.783' 

;WITH CTE AS 
(
    SELECT @FROMDATE FROMDATE 
    UNION ALL 
    SELECT DATEADD(HH,1,FROMDATE) 
    FROM CTE 
    WHERE FROMDATE<@TODATE 
) 
SELECT ISNULL(CAST(CAST(FROMDATE AS DATE)AS VARCHAR(12)),'Tot')FROMDATE, 
CAST(COUNT(FROMDATE)AS VARCHAR(4))+'hrs' [HOURS] 
FROM CTE 
WHERE DATEPART(HH,FROMDATE) BETWEEN 9 AND 16 
AND DATENAME(DW,FROMDATE)<>'SATURDAY' AND DATENAME(DW,FROMDATE)<>'SUNDAY' 
GROUP BY CAST(FROMDATE AS DATE) 
WITH ROLLUP 

МЕТОД 2: получает отсутствующий период между FromDate и Todate с 8 как hardcoded as Hrs

Этот метод будет более осуществимым - Производительность Tuned

DECLARE @FROMDATE DATETIME='2014-12-17 14:01:03.523' 
DECLARE @TODATE DATETIME='2014-12-20 09:59:28.783' 

;WITH CTE AS 
(
    -- Get missing dates between FromDate and ToDate 
    SELECT DATEADD(DAY,1,@FROMDATE) FROMDATE,8 HRS 
    UNION ALL 
    SELECT DATEADD(DAY,1,FROMDATE),8 
    FROM CTE 
    WHERE FROMDATE < DATEADD(DAY,-1,@TODATE) 
) 
,CTE2 AS 
(
    -- Gets the Hours for FromDate 
    SELECT CAST(@FROMDATE AS DATE) DATES, CAST(CAST(DATEDIFF 
    (
     MINUTE,@FROMDATE,CAST(CAST(CAST(@FROMDATE AS DATE) AS VARCHAR(12))+' 17:00:00' AS DATETIME) 
    )AS NUMERIC(18,2))/60 AS DECIMAL(18,0)) HRS 
    WHERE DATENAME(DW,@FROMDATE)<>'SATURDAY' AND DATENAME(DW,@FROMDATE)<>'SUNDAY' 

    UNION ALL 

    -- Select Hours in between dates 
    SELECT CAST(FROMDATE AS DATE) NEWDATE,HRS 
    FROM CTE 
    WHERE DATENAME(DW,FROMDATE)<>'SATURDAY' AND DATENAME(DW,FROMDATE)<>'SUNDAY' 

    UNION ALL 

    -- Select Hours for ToDate 
    SELECT CAST(@TODATE AS DATE), CAST(CAST(DATEDIFF 
    (
     MINUTE,CAST(CAST(CAST(@TODATE AS DATE) AS VARCHAR(12))+' 08:00:00' AS DATETIME),@TODATE 
    )AS NUMERIC(18,2))/60 AS DECIMAL(18,0)) 
    WHERE DATENAME(DW,@TODATE)<>'SATURDAY' AND DATENAME(DW,@TODATE)<>'SUNDAY' 
) 
-- Use ROLLUP to find the sum of Hours and show it in last row 
SELECT ISNULL(CAST(DATES AS VARCHAR(20)),'Tot')DATES, 
CAST(SUM(HRS)AS VARCHAR(4))+'hrs' HRS 
FROM CTE2 
GROUP BY DATES 
WITH ROLLUP 
0

@marco burrometo

Создать статическую таблицу, которая будет иметь все календарную функциональность как функциональность праздника , суббота и воскресенье - праздник. Это вам очень поможет.

Смежные вопросы