我正在寻找一个T-Sql脚本来计算两个日期之间的总小时数,但前提是它只属于某个时期。
我有一个名为Complaints的表,其中包含各种列,包括ContactDate和ResolvedDate。
如果它在我们的营业时间内,我只想计算以小时计的总时间。周一至周五下午9点至5点,周六和周日下午12点至下午4点。
例如,如果我在12月5日下午3点收到投诉,并在12月6日下午1点解决,则总时数为3小时。
另一个例子是我在12月3日和12点收到投诉并于12月6日下午5点解决,总时数为24小时。
我希望将这个值拉入我的报告的每一行。
答案 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
返回
作为额外奖励,您可以排除假期以及(应该是实际的表格)
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))