这是一个更复杂的问题,然后我认为您对此表示赞赏。您需要考虑到工作时间以外的日子和时间。这将包括任何假期、半天、办公室关闭等。最好通过维护一个被视为工作时间的日期、小时甚至分钟表来处理。
如果您不想要一个仅用于此目的的表格,则可以使用一个简单的 Dates 表格以及第二张规则表格,说明何时将特定日期或时间视为工作时间你来推导出这个。
如果您甚至没有,则每次要运行查询时都需要派生您的表,并包括 所有 的工作此查询中的时间 规则。创建datetime 值表的最有效方法是 Tally 表,在您的情况下可以按如下方式使用:
declare @DateAssigned datetime = '05-04-2017 13:00:00';
declare @DayStart time = '08:00:00';
declare @DayEnd time = '17:30:00';
declare @SLAMinutes int = 480; -- 8 hours * 60 minutes per hour
-- cte to create a table with 10 rows in
with n(n) as (select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1 union all select 1)
-- cte to cross join the rows together, resulting in 10^6 (1 million) rows. Add or remove joins per number of minutes required.
-- Use the row_number function to add an incremental number of minutes to the original @DateAssigned to get a table of minutes from the @DateAssigned value.
,t(t) as (select dateadd(minute,row_number() over(order by (select null))-1,@DateAssigned) from n n1, n n2, n n3, n n4, n n5, n n6)
-- Select the first @SLANumber number of rows that meet your Working Time criteria. We add 2 to this value do resolve the fencepost problem.
,d(d) as (select top (@SLAMinutes + 2) t
from t
where cast(t as time) >= @DayStart -- Only return minutes from 08:00 onwards.
and cast(t as time) <= @DayEnd -- Only return minutes up to 17:30.
and datepart(weekday,t) not in (7,1) -- Only return minutes not on Saturday or Sunday.
order by t)
-- The MAX value in the cte d will be the last minute of your SLA window.
select @DateAssigned as DateAssigned
,max(d) as SLADeadline
from d;
哪些输出:
+-------------------------+-------------------------+
| DateAssigned | SLADeadline |
+-------------------------+-------------------------+
| 2017-05-04 13:00:00.000 | 2017-05-05 11:30:00.000 |
+-------------------------+-------------------------+