Создание временных интервалов между двумя часами на сегодня - PullRequest
0 голосов
/ 06 августа 2020

Я немного редактирую свой вопрос

У меня есть следующая таблица рабочего времени:

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.00, время окончания - 18.00 с перерывом между .Это время может варьироваться в зависимости от выбранного офиса.

Входные параметры:

1. Время в пути до офиса в минутах

2. Продолжительность временного интервала в минутах

Принимая во внимание время в пути в минутах, я хочу сгенерировать временные интервалы с 15-минутным (переменным) интервалом между этими временными диапазонами, например

7.00 AM

7.15 AM

7.30

7,45

8.00.

.

.

.

13:30

1.45 PM

14.00

Здесь начинается вторая смена

16.00

16.15

16.30

.

.

.

.

.

17.30

5.45 PM

Сценарий 1:

Путешествие необходимое время: 31 минута

Время попытки бронирования 6.15 AM

Время работы офиса 7.00 AM

Требуемый результат

7.00

7.15

.

. 1.45 PM (не включая время окончания смены 14.00)

16.00

16.15

.

. 17.45

Сценарий 2:

Необходимое время в пути: 31 минута

Время попытки бронирования 6.45 AM

Время открытия офиса 7.00 AM

Требуемый результат

7,16

7,31

.

. 1.46 PM (не включая время окончания смены 14.00)

16.00

16.15

.

. 17.45

Сценарий 3:

Необходимое время в пути: 31 минута

Время попытки бронирования 9.45 AM

Время открытия офиса 7.00 AM

Требуемый результат

10,16

10,31

.

. 1.46 PM (не включая время окончания смены 14.00)

16.00

16.15

.

. 17.45

Сценарий 4:

Время в пути: 31 минута

Время попытки бронирования 15:00

Офис Открытие второй смены Время 16.00

Требуемый результат

16.00

16.15

.

. 17.45 (не включая время окончания смены 18.00)

Сценарий 5:

Необходимое время в пути: 31 минута

Время попытки бронирования 15.45

Офис Открытие второй смены Время 16.00

Требуемый результат

16.16

16.31

.

. 17.46 (не включая время окончания смены 18.00)

Ответы [ 2 ]

1 голос
/ 06 августа 2020
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;

0 голосов
/ 07 августа 2020

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;  

Что он делает: Работа запроса выполняется в 2 CTE и выборе с их помощью:

  1. time_range: определяет необходимое время начала и окончания с учетом текущего времени (на сервере).
  2. office_hours: рекурсивный CTE, который вычисляет 15-минутные интервалы для времени начала и окончания.
  3. Main: выберите начало диапазона и определяет сдвиг.

См. скрипт для пример . Примечание: в текущей форме запрос всегда будет возвращать как минимум 1 строку. Если выполняется после времени окончания, он возвращает указание строки этого времени. Есть два дополнительных запроса с небольшой модификацией, позволяющие указать фактическое время выполнения вместо получения его из системы. для них я "установил время выполнения" на 07:00 и 09:02 соответственно.

...