задания можно регистрировать в любое время суток с помощью онлайн-форм, а не только с 8:00 до 17:00
Это означает, что если задание заносится в нерабочее времяВы должны обращаться с ним так, как если бы он был фактически зарегистрирован в начале следующего рабочего дня.(Обратите внимание, что я следую вашему вопросу, рассматривая все пн-пт как рабочие дни - например, в вашем вопросе о праздничных днях ничего нет. Работа с ними, вероятно, будет отдельным вопросом.)
Если выЕсли вы хотите разбить его на части, вы можете сначала выяснить, когда часы запускаются для данной работы, основываясь на том, были ли они зарегистрированы в течение или вне рабочего дня.Есть несколько способов сделать это, но так как вам приходится иметь дело с выходными, я решил сделать это следующим образом:
select id, priority_code, logged_time,
case
when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Fri'
and floor((logged_time - trunc(logged_time)) * 24) >= 17
then trunc(logged_time) + 56/24
when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Sat'
then trunc(logged_time) + 56/24
when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Sun'
or floor((logged_time - trunc(logged_time)) * 24) >= 17
then trunc(logged_time) + 32/24
when floor((logged_time - trunc(logged_time)) * 24) < 8
then trunc(logged_time) + 8/24
else logged_time
end as clock_start
from your_table;
floor((logged_time - trunc(logged_time)) * 24)
дает вам час, когда работа была зарегистрирована, поэтому выможно увидеть, было ли это меньше, чем 8 (то есть 8 утра) или больше или равно 17 (то есть 5 вечера).Для рабочих мест, зарегистрированных в 17:00 или позже в пятницу или в любое время в выходные дни, время начала работы переносится на следующий понедельник;задания, зарегистрированные в 17:00 или позднее в другие дни, переносятся на следующее утро.Используется арифметика даты - 8/24 - это 8 часов, 32/24 - это 1 день и 8 часов, 56/24 - это 2 дня и 8 часов и т. Д.
Затем вы можете поместить это во встроенное представление или CTE.чтобы упростить дальнейшие вычисления:
with cte1 (id, priority_code, logged_time, clock_start) as (
...
)
select id, priority_code, logged_time, clock_start,
clock_start
+ case priority_code when 'GC04' then 1 when 'GC05' then 2 when 'GC06' then 4 end
/ 24 as target_time
from cte1;
, который даст вам базовое целевое время;и затем вы можете настроить , что , используя логику, аналогичную моей предыдущей статье о метках времени и ведении журнала только для рабочих дней, но на этот раз, используя больше манипуляций с датой в дробных днях, а не с интервалами:
with cte1 (id, priority_code, logged_time, clock_start) as (
select id, priority_code, logged_time,
case
when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Fri'
and floor((logged_time - trunc(logged_time)) * 24) >= 17
then trunc(logged_time) + 80/24
when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Sat'
then trunc(logged_time) + 56/24
when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Sun'
or floor((logged_time - trunc(logged_time)) * 24) >= 17
then trunc(logged_time) + 32/24
when floor((logged_time - trunc(logged_time)) * 24) < 8
then trunc(logged_time) + 8/24
else logged_time
end as clock_start
from your_table
),
cte2 (id, priority_code, logged_time, clock_start, target_time) as (
select id, priority_code, logged_time, clock_start,
clock_start
+ case priority_code when 'GC04' then 1 when 'GC05' then 2 when 'GC06' then 4 end
/ 24 as target_time
from cte1
)
select id, priority_code, logged_time, clock_start,
case
when to_char(target_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Fri'
and floor((target_time - trunc(target_time)) * 24) >= 17
then target_time + 63/24
when floor((target_time - trunc(target_time)) * 24) >= 17
then target_time + 15/24
else target_time
end as target_time
from cte2;
, который с некоторыми выдуманными данными для сценариев, о которых я думал, дает, с днями, добавленными только для информации, чтобы, надеюсь, немного прояснить ситуацию:
ID PRIO LOGGED_TIME CLOCK_START TARGET_TIME LOGGED_DAY CLOCK_DAY TARGET_DAY
--- ---- ------------------- ------------------- ------------------- ---------- --------- ----------
1 GC06 2019-05-27 12:59:59 2019-05-27 12:59:59 2019-05-27 16:59:59 Mon Mon Mon
2 GC06 2019-05-27 13:15:00 2019-05-27 13:15:00 2019-05-28 08:15:00 Mon Mon Tue
3 GC05 2019-05-27 14:59:59 2019-05-27 14:59:59 2019-05-27 16:59:59 Mon Mon Mon
4 GC05 2019-05-27 15:15:00 2019-05-27 15:15:00 2019-05-28 08:15:00 Mon Mon Tue
5 GC04 2019-05-27 15:59:59 2019-05-27 15:59:59 2019-05-27 16:59:59 Mon Mon Mon
6 GC04 2019-05-27 16:15:00 2019-05-27 16:15:00 2019-05-28 08:15:00 Mon Mon Tue
7 GC04 2019-05-27 16:59:59 2019-05-27 16:59:59 2019-05-28 08:59:59 Mon Mon Tue
8 GC04 2019-05-27 17:00:00 2019-05-28 08:00:00 2019-05-28 09:00:00 Mon Tue Tue
9 GC04 2019-05-28 07:59:59 2019-05-28 08:00:00 2019-05-28 09:00:00 Tue Tue Tue
10 GC04 2019-05-28 08:00:00 2019-05-28 08:00:00 2019-05-28 09:00:00 Tue Tue Tue
11 GC06 2019-05-31 12:59:59 2019-05-31 12:59:59 2019-05-31 16:59:59 Fri Fri Fri
12 GC06 2019-05-31 13:15:00 2019-05-31 13:15:00 2019-06-03 08:15:00 Fri Fri Mon
13 GC05 2019-05-31 14:59:59 2019-05-31 14:59:59 2019-05-31 16:59:59 Fri Fri Fri
14 GC05 2019-05-31 15:15:00 2019-05-31 15:15:00 2019-06-03 08:15:00 Fri Fri Mon
15 GC04 2019-05-31 15:59:59 2019-05-31 15:59:59 2019-05-31 16:59:59 Fri Fri Fri
16 GC04 2019-05-31 16:15:00 2019-05-31 16:15:00 2019-06-03 08:15:00 Fri Fri Mon
17 GC04 2019-05-31 16:59:59 2019-05-31 16:59:59 2019-06-03 08:59:59 Fri Fri Mon
18 GC04 2019-05-31 17:00:00 2019-06-03 08:00:00 2019-06-03 09:00:00 Fri Mon Mon
19 GC04 2019-06-01 12:00:00 2019-06-03 08:00:00 2019-06-03 09:00:00 Sat Mon Mon
20 GC04 2019-06-02 12:00:00 2019-06-03 08:00:00 2019-06-03 09:00:00 Sun Mon Mon
21 GC04 2019-06-03 07:59:59 2019-06-03 08:00:00 2019-06-03 09:00:00 Mon Mon Mon
22 GC04 2019-06-03 08:00:00 2019-06-03 08:00:00 2019-06-03 09:00:00 Mon Mon Mon
db <> fiddle
Обратите внимание, что конструкция CTE предоставляет псевдонимы для выражения столбца из условия with (...)
, и что у них нет псевдонимов таблиц - поскольку эти псевдонимы не связаны с таблицами внутриКТР.Так что with cte1 (id, priority_code, ...
и не with cte1 (your_table.id, your_table.priority_code, ...
.
Также обратите внимание, что точка с запятой в конце является разделителем операторов, обязательным или необязательным (или настраиваемым) в некоторых клиентах, но недопустимым вдругие - это может вызвать ошибки ORA-00933 или ORA-00911 и, возможно, другие, в динамическом SQL, JDBC и т. д .;поэтому ODBC, вероятно, также не ожидает увидеть этот последний символ точки с запятой.
Если ODBC (или ваша версия) не допускает CTE, что было предложено из-за ошибки «not SELECT Statement», которую вы упомянули в комментарии, -тогда вместо этого вы можете использовать встроенные представления:
select id, priority_code, logged_time, clock_start,
case
when to_char(target_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Fri'
and floor((target_time - trunc(target_time)) * 24) >= 17
then target_time + 2 + 63/24
when floor((target_time - trunc(target_time)) * 24) >= 17
then target_time + 15/24
else target_time
end as target_time
from (
select id, priority_code, logged_time, clock_start,
clock_start
+ case priority_code when 'GC04' then 1 when 'GC05' then 2 when 'GC06' then 4 end
/ 24 as target_time
from (
select id, priority_code, logged_time,
case
when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Fri'
and floor((logged_time - trunc(logged_time)) * 24) >= 17
then trunc(logged_time) + 80/24
when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Sat'
then trunc(logged_time) + 56/24
when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Sun'
or floor((logged_time - trunc(logged_time)) * 24) >= 17
then trunc(logged_time) + 32/24
when floor((logged_time - trunc(logged_time)) * 24) < 8
then trunc(logged_time) + 8/24
else logged_time
end as clock_start
from your_table
)
);
Добавлено в db <> fiddle .
Немного неясно, но сохранить предварительно рассчитанныйtarget_comp_date
для других приоритетов вы можете изменить первое встроенное представление (на основе cte2), чтобы оно содержало вложенные выражения регистра:
...
from (
select id, priority_code, logged_time, clock_start,
case when priority_code in ('GC04', 'GC05', 'GC06') then
-- for these, calculate the target time based on clock-start as before
clock_start
+ case priority_code when 'GC04' then 1 when 'GC05' then 2 when 'GC06' then 4 end
/ 24
else
-- for any other priority use the original pre-calculated time
target_comp_date
end as target_time
from (
select id, priority_code, logged_time, target_comp_date,
...
Самое внутреннее встроенное представление должно включать этот дополнительный столбец в свой список выбора, поэтомувидимое этому вложенному выражению регистра.
Система покажет target_comp_date неверно, как 12 am
Возможно, вам следует исправить этот существующий код, а не пытаться обманутьрезультат, который он вам дает.