使用T-SQL的日期之间的总小时数

时间:2016-12-07 16:06:07

标签: sql tsql ssms

我正在寻找一个T-Sql脚本来计算两个日期之间的总小时数,但前提是它只属于某个时期。

我有一个名为Complaints的表,其中包含各种列,包括ContactDate和ResolvedDate。

如果它在我们的营业时间内,我只想计算以小时计的总时间。周一至周五下午9点至5点,周六和周日下午12点至下午4点。

例如,如果我在12月5日下午3点收到投诉,并在12月6日下午1点解决,则总时数为3小时。

另一个例子是我在12月3日和12点收到投诉并于12月6日下午5点解决,总时数为24小时。

我希望将这个值拉入我的报告的每一行。

3 个答案:

答案 0 :(得分:0)

是的,我没有为你做所有这些,但这会给你一个选择。我创建了一个每小时都有一行数据的表。在这个我会有一个标志,以显示它是否是一个工作小时,像这样;

CREATE TABLE #DateTable (Time_Stamp datetime, Working_Hour int)
INSERT INTO #DateTable (Time_Stamp, Working_Hour)
VALUES
 ('2016-12-05 14:00:00',1)
,('2016-12-05 15:00:00',1)
,('2016-12-05 16:00:00',1)
,('2016-12-05 17:00:00',0)
,('2016-12-05 18:00:00',0)
,('2016-12-05 19:00:00',0)
,('2016-12-05 20:00:00',0)
,('2016-12-05 21:00:00',0)
,('2016-12-05 22:00:00',0)
,('2016-12-05 23:00:00',0)
,('2016-12-05 00:00:00',0)
,('2016-12-06 01:00:00',0)
,('2016-12-06 02:00:00',0)
,('2016-12-06 03:00:00',0)
,('2016-12-06 04:00:00',0)
,('2016-12-06 05:00:00',0)
,('2016-12-06 06:00:00',0)
,('2016-12-06 07:00:00',0)
,('2016-12-06 08:00:00',0)
,('2016-12-06 09:00:00',0)
,('2016-12-06 10:00:00',0)
,('2016-12-06 11:00:00',0)
,('2016-12-06 12:00:00',1)
,('2016-12-06 13:00:00',1)
,('2016-12-06 14:00:00',1)
,('2016-12-06 15:00:00',1)

样本呼叫清单;

CREATE TABLE #Calls (Call_ID int, StartDate datetime, EndDate datetime)
INSERT INTO #Calls (Call_ID, StartDate, EndDate)
VALUES
 (1,'2016-12-05 14:00:00','2016-12-06 14:00:00')
,(2,'2016-12-05 15:00:00','2016-12-06 14:00:00')
,(3,'2016-12-05 16:00:00','2016-12-06 14:00:00')

通过这种方式,你可以使用你的两个日期加入这个,并总结它们之间的工作时间,就像这样;

SELECT
     c.Call_ID
    ,SUM(dt.Working_Hour) Working_Hour
FROM #Calls c
JOIN #DateTable dt
    ON dt.Time_Stamp BETWEEN c.StartDate AND c.EndDate
GROUP BY c.Call_ID

结果;

Call_ID Working_Hour
1       6
2       5
3       4

如果你google' date table sql'有很多例子可以帮助你填充日期表。

答案 1 :(得分:0)

从我以前做过的记忆中......(它不太漂亮)

with CTE as
(
select CaseID, cast(ComplaintDate as date) as ComplaintDate, cast(CompaintDate as time) as CompTime, cast(ResolvedDate as date) as ResolvedDate, cast(ResolvedDate as time) as ResolvedTime,
case
  when datepart(dw,ResolvedDate) in (1,7) then cast('12:00:00' as TIME)
  else cast('09:00:00' as time)
end as ResStart,
case
  when datepart(dw,CompaintDate) in (1,7) then cast('16:00:00') as time
  else cast('17:00:00' as time)
end as ComEnd
from Compaints
)
select CaseID,
case
when datepart(dd, ResolvedDate) > datepart(dd,ComplaintDate) then
  datediff(hh, ResolvedTime, ResStart) + datediff(hh,ComEnd,ComplaintTime) + 8*datediff(dd,ResolvedDate,ComplaintDate)
else DateDiff(hh,ResolvedTime,ComplaintTime)
end as HoursOpen
from CTE

答案 2 :(得分:0)

请考虑以下事项。

我们实际上在几分钟内执行计算,因此您决定向上/向下舍入,但结果将在几小时内返回。

我应该注意,CROSS APPLY中的代码可以很容易地迁移到UDF中。

Declare @YourTable table (ID int,OpenDT datetime, CloseDT datetime)
Insert Into @YourTable values
(1,'2016-12-02 16:00','2016-12-05 10:00'),
(2,'2016-12-02 16:00','2016-12-05 09:45'),
(3,'2016-12-07 09:00','2016-12-08 11:15')

Select A.*
      ,B.BusinessHours
 From  @YourTable A
 Cross Apply (
                Select BusinessHours=count(*)/60.0 
                 From (Select Top (DateDiff(MI,A.OpenDT,A.CloseDT)+5000) D=DateAdd(MI,Row_Number() over (Order By (Select NULL))-1,cast(cast(A.OpenDT as date) as datetime)) From master..spt_values N1,master..spt_values N2) D
                 Where  D > A.OpenDT and D<= A.CloseDT
                   and (
                        (DatePart(DW,D) between 2 and 6 and cast(D as time) between '09:01' and '17:00') 
                        or  
                        (DatePart(DW,D) = 7 and cast(D as time) between '12:01' and '16:00')
                        )
       ) B

返回

enter image description here

作为额外奖励,您可以排除假期以及(应该是实际的表格)

and  Cast(D as Date) Not In (Select Date From (Values 
                                       ('2016-01-01','New Year''s Day'),
                                       ('2016-01-18','Martin Luther King, Jr,'),
                                       ('2016-02-15','Washington''s Birthday'),
                                       ('2016-03-25','Good Friday'),
                                       ('2016-05-30','Memorial Day'),
                                       ('2016-07-04','Independence Day'),
                                       ('2016-09-05','Labor Day'),
                                       ('2016-11-24','Thanksgiving'),
                                       ('2016-11-25','Black Friday'),
                                       ('2016-12-26','Christmas Day') 
                                ) as H (Date,Name))