计算经过时间 (DATEDIFF),同时减去休息和午餐时间

Calculate elapsed time (DATEDIFF) while subtracting time for break and lunch periods

我有一个 table 看起来像:

job | start_time               | end_time
----------------------------------------------------------
1   | 2020-08-31 09:46:00.000  |  2020-08-31 12:37:00.000
2   | 2020-08-31 09:54:00.000  |  2020-08-31 10:24:00.000
3   | 2020-08-31 05:52:00.000  |  2020-08-31 06:32:00.000
4   | 2020-08-31 05:02:00.000  |  2020-08-31 13:24:00.000

我需要计算 start_timeend_time 之间的 elapsed_time 分钟,但如果 elapsed_time 跨越 8:45am9:00am and/or 30 分钟如果 elapsed_time 跨越 11:30am12:00pm.

输出应如下所示:

job | start_time               | end_time                 | elapsed_time
-------------------------------------------------------------------------
1   | 2020-08-31 09:46:00.000  |  2020-08-31 12:37:00.000 | 141
2   | 2020-08-31 09:54:00.000  |  2020-08-31 10:24:00.000 | 30
3   | 2020-08-31 05:52:00.000  |  2020-08-31 06:32:00.000 | 40
4   | 2020-08-31 05:02:00.000  |  2020-08-31 13:24:00.000 | 457

感谢您的帮助!

编辑:

我目前计算分钟数:

SELECT DATEDIFF(minute, start_time, end_time) FROM jobtran

然后将数据集导出到 excel 并从那里手动计算。

以下 returns 所提供样本数据的预期结果。然而,它假设一个时间段总是在一天之内。并且它假定没有时间段在休息时间内开始或结束(我将把它留给你作为练习)。

诀窍是使用 case 表达式来检测何时发生重叠并针对它进行调整。

另请注意 sub-query/derived table 的使用,以避免在整个查询过程中重复相同的转换和静态值。

declare @Test table (job int, start_time datetime, end_time datetime);

insert into @Test (job, start_time, end_time)
values
(1, '2020-08-31 09:46:00.000',  '2020-08-31 12:37:00.000'),
(2, '2020-08-31 09:54:00.000',  '2020-08-31 10:24:00.000'),
(3, '2020-08-31 05:52:00.000',  '2020-08-31 06:32:00.000'),
(4, '2020-08-31 05:02:00.000',  '2020-08-31 13:24:00.000');

select job, start_time, end_time
  , datediff(minute, start_time, end_time) [Total Mins]
  , datediff(minute, start_time, end_time)
  - case when start_time < end_break and end_time > start_break then 15 else 0 end
  - case when start_time < end_lunch and end_time > start_lunch then 30 else 0 end [Adjusted Mins]
from (
  select job
    , convert(time, start_time) start_time
    , convert(time, end_time) end_time
    , convert(time, '08:45am') start_break
    , convert(time, '09:00am') end_break
    , convert(time, '11:30am') start_lunch
    , convert(time, '12:00pm') end_lunch
  from @Test
) X;

结果

job | start_time                | end_time                  | Total Mins    | Adjusted Mins
------------------------------------------------------------------------------------------
1   | 2020-08-31 09:46:00.000   | 2020-08-31 12:37:00.000   | 171           | 141
2   | 2020-08-31 09:54:00.000   | 2020-08-31 10:24:00.000   | 30            | 30
3   | 2020-08-31 05:52:00.000   | 2020-08-31 06:32:00.000   | 40            | 40
4   | 2020-08-31 05:02:00.000   | 2020-08-31 13:24:00.000   | 502           | 457

需要考虑的事项 if/when 考虑开始或结束于 break/lunch 的时间段:

  1. 如果一个时间段开始 并且 在一个时间段内结束,那么总分钟数应该为零 - 这是一种特殊情况,一旦处理,您就可以忽略其余部分逻辑。
  2. 如果在休息期间中途开始,则要减去的时间量是期间开始时间与休息结束时间之间的差值。
  3. 如果您在休息期间中途结束,则要减去的时间量是休息开始时间和期间结束时间之间的差值。

注意:如果您以后像这样设置示例数据,您将更快地获得帮助。