我正在创建一个查询,显示两个日期之间经过的时间,仅考虑周一至周五08:00至17:00之间的时间,例如:
例如,如果请愿书在第1天下午6:30开放。并且在第2天晚上8:45关闭,TMO是45分钟。 如果它在第3天8:45关闭,则TMO为9小时45分钟。
示例2: 如果请愿书在周五16:45开放,周二8:30关闭,则MTO将是:周五15分钟,周一9小时,周二30分钟,MTO = 9小时45分钟
查询是在类型为date的单列上执行的,如下所示
我目前使用LAG函数进行查询,但我无法创建功能性的内容,甚至无法合并,我非常感谢您的帮助。
答案 0 :(得分:1)
在下面的解决方案中,我将忽略"滞后"问题的一部分,你说你知道如何使用。我只是展示如何计算"工作时间"在任何两个date_times之间(它们可能在工作时间期间或之前或之后,和/或它们可以在周末时间;在所有情况下计算都相同)。
用文字解释答案:对于两个给定的日期时间,"开始"并且"结束",计算有多少"工作"从一周开始(从星期一00:00:00)到他们每个人的小时数。这实际上是一个日期的计算,而不是两个日期的计算。然后:给出"开始"和"结束",计算每个小时的这个小时数;减去"结束"来自"开始"的小时数小时数。结果,添加x乘以5乘以9,其中x是两个日期的星期一00:00:00之间的星期差异。 (如果它们在同一周,差异将为0.)
要将日期截断到当天的开头,我们会使用TRUNC(dt)
。截断到星期一的开始,TRUNC(dt, 'iw')
。
计算有多少"工作"小时是从dt
日期开始到我们可以使用计算的实际时间
greatest(0, least(17/24, dt - trunc(dt)) - 8/24)
(结果将以天为单位;我们以天计算所有内容,然后我们可以转换为小时)。但是,在最终公式中,我们必须检查日期是星期六还是星期日,在这种情况下,这应该只是零。或者,更好的是,我们可以稍后调整计算,当我们从星期一开始计算时(我们可以使用least( 5*9/24, ...)
)。
把所有东西放在一起:
with
inputs ( dt1, dt2 ) as (
select to_date('2017-09-25 11:30:00', 'yyyy-mm-dd hh24:mi:ss'),
to_date('2017-10-01 22:45:00', 'yyyy-mm-dd hh24:mi:ss')
from dual
)
-- End of SIMULATED input dates (for testing only).
select 24 *
( least(5 * (17 - 8) / 24, greatest(0, least(17/24, dt2 - trunc(dt2)) - 8/24)
+ (17 - 8) / 24 * (trunc(dt2) - trunc(dt2, 'iw')))
-
least(5 * (17 - 8) / 24, greatest(0, least(17/24, dt1 - trunc(dt1)) - 8/24)
+ (17 - 8) / 24 * (trunc(dt1) - trunc(dt1, 'iw')))
+ 5 * (17 - 8) / 24 * (trunc(dt2, 'iw') - trunc(dt1, 'iw')) / 7
)
as duration_in_hours
from inputs
;
DURATION_IN_HOURS
-----------------
41.500