我正在编辑我的问题
我有办公室时间表如下。
TIME_FROM TIME_TO TIME_FROM1 TIME_TO1 TIME_FROM2 TIME_TO2
07:00 AM 14:00 PM 700 1400 06/08/2020 07:00:00 AM 06/08/2020 02:00:00 PM
16:00 PM 18:00 PM 1600 1800 06/08/2020 04:00:00 PM 06/08/2020 06:00:00 PM办公开始时间为上午7点,结束时间为下午6点,between.This时间中的休息时间可根据所选的办公时间而变化。
输入参数为
1.到达办公室以分钟为单位的旅行时间
2.时隙持续时间(分钟)
在考虑旅行时间(以分钟为单位)之后,我希望在这些时间段之间生成15分钟(可变)间隔的时隙,如
上午7时
上午7时15分
上午7时30分
上午7时45分
上午8点
。
。
。
下午1时30分
下午1.45
下午2时
第二班从这里开始
下午4:00
下午4:15
下午4时30分
。
。
。
。
。
下午5时30分
下午5.45
场景1 :
所需旅行时间:31分钟
预订时间上午6时15分
办公时间上午7时
所需结果
7.00
7.15
。
。下午1.45 (不包括下班结束时间下午2点)
下午4:00
下午4:15
。
。下午5.45
场景2 :
所需旅行时间:31分钟
预订时间上午6时45分
办公时间上午7时
所需结果
7.16
7.31
。
。下午1.46 (不包括下班结束时间下午2点)
下午4:00
下午4:15
。
。下午5.45
场景3 :
所需旅行时间:31分钟
预订时间上午9时45分
办公时间上午7时
所需结果
10.16
10.31
。
。下午1.46 (不包括下班结束时间下午2点)
下午4:00
下午4:15
。
。下午5.45
场景4 :
所需旅行时间:31分钟
预约时间下午3:00
办公室第二班开放时间下午4:00
所需结果
下午04.00
下午04.15
。
。下午5.45 (不包括下班结束时间下午18时)
场景5 :
所需旅行时间:31分钟
预约时间下午3.45
办公室第二班开放时间下午4:00
所需结果
04.16下午
下午04.31
。
。下午5.46 (不包括下班结束时间下午18时)
发布于 2020-08-06 09:04:27
WITH
--cte to determine office hours, this is probably a table irl
office_timing (id, time_from2, time_to2) AS
(
SELECT 1, TO_DATE('09/08/2020 07:00:00 AM','DD/MM/YYYY HH:MI:SS AM'), TO_DATE('09/08/2020 02:00:00 PM','DD/MM/YYYY HH:MI:SS AM') FROM dual UNION ALL
SELECT 2, TO_DATE('09/08/2020 04:00:00 PM','DD/MM/YYYY HH:MI:SS AM'), TO_DATE('09/08/2020 06:00:00 PM','DD/MM/YYYY HH:MI:SS AM') FROM dual
)
--cte to determine when travel time to office, replace with other values to test. Make this a variable if it is an input parameter
,travel_time (travel_mins) AS
(
SELECT 31 FROM DUAL
)
--cte to determine slot length, replace with other values to test. Make this a variable if it is an input parameter
,
slot_minutes (mins) AS
(
SELECT 15 FROM DUAL
)
--cte to determine when query is run, replace with other values to test. Make this a variable if it is an input parameter
,run_date_tab (run_date) AS
(
SELECT
TO_DATE('09/08/2020 03:45:00 PM','DD/MM/YYYY HH:MI:SS AM') + travel_mins/1440
FROM travel_time
)
--cte to determine start time based on the query run date
-- if run date is in a time slot then take run date
-- if run date is outside time slot then take closest future start date
,
start_time_tab (qry_start_time) AS
(
SELECT MIN(CASE
WHEN t.time_from2 <= r.run_date AND t.time_to2 > r.run_date
THEN r.run_date
WHEN t.time_from2 > r.run_date
THEN t.time_from2
ELSE
NULL
END)
FROM run_date_tab r
CROSS JOIN office_timing t
)
,slots (slot_start_time) AS
(
SELECT
s.qry_start_time +(level - 1) / ((60/m.mins)*24)
FROM start_time_tab s CROSS JOIN slot_minutes m CONNECT BY
level < 100
)
SELECT TO_CHAR(s.slot_start_time,'DD/MM/YYYY HH:MI:SS AM')
FROM slots s
JOIN office_timing t ON t.time_from2 < s.slot_start_time AND t.time_to2 > s.slot_start_time;发布于 2020-08-06 21:12:42
Oracle提供了相当全面的日期(包括时间戳)处理功能。通常,我遵循这样一条公理:一旦一列被转换为日期,转换为字符串的唯一理由就是创建一个显示列。但也有例外。其中之一是(通常是)当日期需要切片,切块和重新组装。这里的情况是按照“匹配分钟运行”的要求正确计算结束时间。
您不会从SQL解决方案中获得换档中断线,至少我会这样做。您可以通过迭代结果来使用PL/SQL。但是,对于表示层来说,这是一个简单的任务。我在最后结果中添加了一列,表示移位。考虑到这一点:
with time_range (sts, ets) as
( select case when extract(hour from systimestamp) <= 07
then trunc(systimestamp) + interval '07:00' hour to minute
else trunc(systimestamp, 'mi')
end sot
, case when extract(hour from systimestamp) <= 07
then trunc(systimestamp) + interval '18:00' hour to minute
else to_timestamp(to_char(systimestamp,'yyyymmdd') || '18' || to_char(systimestamp,'mi'), 'yyyymmddhh24mi')
end eot
from dual
)
, office_hours (start_time, end_time) as
( select * from time_range
union all
select start_time+interval '15' minute, end_time
from office_hours
where start_time < end_time
)
select to_char(start_time, 'hh.mi am')
, case when 60 * extract(hour from cast( start_time as timestamp))
+ extract(minute from cast( start_time as timestamp)) <= 14*60
then 'first shift'
else 'second shift'
end shift
from office_hours; 它所做的:
查询的工作在两个CTE中完成,并使用它们进行选择:
关于示例,请看小提琴。注意:在当前格式中,查询始终至少返回1行。如果在结束时间之后运行,则返回一个指示时间的行。
还有两个额外的查询,只需稍作修改,允许实际指定运行时,而不是从系统获得。对于这些,我已经将它们中的“运行时”分别设置为07:00和09:02。
https://stackoverflow.com/questions/63279705
复制相似问题