计算经过时间 (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_time
和 end_time
之间的 elapsed_time
分钟,但如果 elapsed_time
跨越 8:45am
和 9:00am
and/or 30 分钟如果 elapsed_time
跨越 11:30am
和 12: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 的时间段:
- 如果一个时间段开始 并且 在一个时间段内结束,那么总分钟数应该为零 - 这是一种特殊情况,一旦处理,您就可以忽略其余部分逻辑。
- 如果在休息期间中途开始,则要减去的时间量是期间开始时间与休息结束时间之间的差值。
- 如果您在休息期间中途结束,则要减去的时间量是休息开始时间和期间结束时间之间的差值。
注意:如果您以后像这样设置示例数据,您将更快地获得帮助。
我有一个 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_time
和 end_time
之间的 elapsed_time
分钟,但如果 elapsed_time
跨越 8:45am
和 9:00am
and/or 30 分钟如果 elapsed_time
跨越 11:30am
和 12: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 的时间段:
- 如果一个时间段开始 并且 在一个时间段内结束,那么总分钟数应该为零 - 这是一种特殊情况,一旦处理,您就可以忽略其余部分逻辑。
- 如果在休息期间中途开始,则要减去的时间量是期间开始时间与休息结束时间之间的差值。
- 如果您在休息期间中途结束,则要减去的时间量是休息开始时间和期间结束时间之间的差值。
注意:如果您以后像这样设置示例数据,您将更快地获得帮助。