简体   繁体   English

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

[英]Total hours between dates using T-SQL

I'm looking for an T-Sql script to calculate total hours between 2 dates, but only if it falls into a certain period. 我正在寻找一个T-Sql脚本来计算两个日期之间的总小时数,但前提是它必须落在某个时期内。

I have a table called Complaints with various columns including ContactDate and ResolvedDate. 我有一个名为Complaints的表,其中包括ContactDate和ResolvedDate。

I only want to calculate the total time in hours if it falls within our opening hours. 如果仅在我们的开放时间之内,我只想计算总时间(以小时为单位)。 9-5pm Mon-Fri and 12-4pm Sat and Sun. 周一至周五晚上9-5时和周六和周日中午12-4时。

So for example, if I got a complaint on the 5th Dec at 3pm and Resolved it on the 6th Dec at 1pm, the total hours would be 3. 因此,举例来说,如果我在12月5日下午3点收到投诉,并在12月6日下午1点解决该问题,则总工作时间为3。

Another example would be I got a complaint on the 3rd Dec and 12pm and Resolved it on the 6th Dec at 5pm, the total hours would be 24 hours. 另一个例子是我在12月3日和12pm收到投诉,并在12月6日5pm解决,总工作时间为24小时。

I would like that value to pull into each row for my report. 我希望该值能进入我的报告的每一行。

Right, I'm not doing all of this for you but this will give you an option. 是的,我不是为您做所有这一切,但这将为您提供一个选择。 I'd create a table with a row of data for each hour. 我将创建一个每小时有一行数据的表。 In this I would have a flag to show whether it is a working hour or not, something like this; 在此,我将有一个标志来显示是否为工作时间,如下所示;

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)

Sample Call List; 呼叫清单样本;

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')

That way you can join to this using your two dates and sum how many working hours between them, like this; 这样,您就可以使用两个日期加入该日期,并总结两个日期之间的工作时间,如下所示:

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

Result; 结果;

Call_ID Working_Hour
1       6
2       5
3       4

If you google 'date table sql' there are plenty of examples to help you populate the date table. 如果您使用Google“日期表sql”,则有很多示例可帮助您填充日期表。

From memory when I did this before... (it's not pretty) 从我以前做这个的记忆中...(不漂亮)

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

Consider the following. 考虑以下。

We actually perform the calculations in minutes so you decide to round up/down, but the result is returned in hours. 实际上,我们以分钟为单位执行计算,因此您决定舍入/舍入,但结果以小时为单位返回。

I should note that the code in the CROSS APPLY could easily be migrated into a UDF. 我应该注意,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

Returns 退货

在此处输入图片说明

As an added bonus, you can exclude holidays as well (should be an actual table) 作为额外的奖励,您还可以排除假期(应为实际表格)

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))   

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM