首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在今天的两次之间生成时隙

在今天的两次之间生成时隙
EN

Stack Overflow用户
提问于 2020-08-06 08:30:18
回答 2查看 766关注 0票数 0

我正在编辑我的问题

我有办公室时间表如下。

代码语言:javascript
复制
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时)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-08-06 09:04:27

代码语言:javascript
复制
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;
票数 1
EN

Stack Overflow用户

发布于 2020-08-06 21:12:42

Oracle提供了相当全面的日期(包括时间戳)处理功能。通常,我遵循这样一条公理:一旦一列被转换为日期,转换为字符串的唯一理由就是创建一个显示列。但也有例外。其中之一是(通常是)当日期需要切片,切块和重新组装。这里的情况是按照“匹配分钟运行”的要求正确计算结束时间。

您不会从SQL解决方案中获得换档中断线,至少我会这样做。您可以通过迭代结果来使用PL/SQL。但是,对于表示层来说,这是一个简单的任务。我在最后结果中添加了一列,表示移位。考虑到这一点:

代码语言:javascript
复制
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. time_range:根据当前时间(在服务器上)确定必要的开始和结束时间。
  2. office_hours:一个递归的CTE,它计算开始到结束时间的15分钟间隔。
  3. 主:选择范围的开始并确定移位。

关于示例,请看小提琴。注意:在当前格式中,查询始终至少返回1行。如果在结束时间之后运行,则返回一个指示时间的行。

还有两个额外的查询,只需稍作修改,允许实际指定运行时,而不是从系统获得。对于这些,我已经将它们中的“运行时”分别设置为07:00和09:02。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63279705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档