TSQL datediff only business hours

混江龙づ霸主 提交于 2019-12-25 02:07:39

问题


In a view have these two dates coming from a table:

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

I need to know the date diff in hours assuming that in a day i can count the hours just from 08 AM and 5 PM.

Of course saturdays and sundays must not be included.

I tried using this code inside the select but i only got the diff in days, excluding saturdays and sundays.

(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

Example:

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

回答1:


Use a Recursive CTE to get all Hours with Dates.

METHOD 1 : Get all dates with hours between FromDate and 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
  • SQL FIDDLE

METHOD 2 : Gets missing dates between FromDate and ToDate with 8 as hardcoded as Hrs

This method will be more implementable - Performance 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
  • SQL FIDDLE



回答2:


@marco burrometo

Create a static table which will have all the calendar functionality like holiday functionality,saturday and sunday is a holiday. It will help you a lot.



来源:https://stackoverflow.com/questions/27945586/tsql-datediff-only-business-hours

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!