Добавьте целевые часы на следующий рабочий день, если задание зарегистрировано через определенное время - PullRequest
0 голосов
/ 31 мая 2019

Бит конкретного запроса / запроса, но надеюсь, что я смогу правильно объяснить его и что он имеет смысл.

  • Рабочий день с 8:00 до 17:00 с понедельника по пятницу
  • Каждое задание имеет целевое время отклика, например, 1 час, 2 часа, 4 часа
  • В некоторых заданиях показывается целевое время отклика вне рабочего дня, например, 4-часовое задание, зарегистрированное в 16:15, покажет цельвремя ответа 8:15 вечера.

Что я хотел бы сделать (и даже не уверен, если это возможно):

Если код_приоритета GC04 (1 час работы)и записанное время - после 16:00 в понедельник-пятницу. Возьмите любое время до 17:00 и добавьте остаток к следующему рабочему дню с 8:00.Так, например, 1 час работы, зарегистрированной в 16:15 в понедельник, покажет целевое время ответа 8:15 утра во вторник.(45 минут используются в понедельник и 15 минут переносятся на вторник).

Если код_приоритета - GC05 (2 часа работы), а зарегистрированное время - после 15:00 в понедельник-пятницу, используйте любое время до 17:00 идобавить остаток на следующий рабочий день с 8 утра.Так, например, 2-часовое задание, зарегистрированное в 15:15 в понедельник, покажет целевое время ответа 8:15 утра во вторник.(1 час 45 минут используется в понедельник и 15 минут переносится на вторник).

Если код_приоритета - GC06 (4-часовое задание), а зарегистрированное время - после 13:00 понедельника-пятницы, принимайте любое время до5 вечера и добавить остаток на следующий рабочий день с 8 утра.Так, например, в 4 часа работы, записанной в понедельник в 13:15, будет показано целевое время ответа 8:15 утра во вторник.(3 часа 45 минут используются в понедельник и 15 минут переносятся на вторник).

СПАСИБО ALEX POOLE, Я СЕЙЧАС ПОЛУЧИЛ ЭТО РАБОТАЮ Кодирование ниже

select job_number, priority_code, job_entry_date, clock_start, 
target_comp_date,
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 job_number, priority_code, job_entry_date, clock_start, 
TARGET_COMP_DATE,
CASE 
WHEN PRIORITY_CODE IN ('GC01','GC02','GC03','GC04','GC05','GC06','GC07') 
THEN
clock_start 
+ case priority_code 
when 'GC01' then 1 
when 'GC02' then 2 
when 'GC03' then 0.5
when 'GC04' then 1 
when 'GC05' then 2 
when 'GC06' then 4
when 'GC07' then 24

end
/ 24 

ELSE
TARGET_COMP_DATE END as target_time

from              (
 select job_number, priority_code, job_entry_date, target_comp_date,
 case
 when to_char(job_entry_date, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Fri'
 and floor((job_entry_date - trunc(job_entry_date)) * 24) >= 17
 then trunc(job_entry_date) + 80/24
     when to_char(job_entry_date, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Sat'
      then trunc(job_entry_date) + 56/24
          when to_char(job_entry_date, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 
 'Sun'
          or floor((job_entry_date - trunc(job_entry_date)) * 24) >= 17
          then trunc(job_entry_date) + 32/24
               when floor((job_entry_date - trunc(job_entry_date)) * 24) < 8
               then trunc(job_entry_date) + 8/24
                    else job_entry_date
  end as clock_start
  from job
                )
     )

Ответы [ 2 ]

2 голосов
/ 31 мая 2019

Немного запутанный подход, который предполагает, что ваш столбец logged_time является временной меткой (легко адаптируемой, если это дата), и что он не может быть вне часов:

select id, priority_code, logged_time,
  logged_time
    +
    -- response time
    (
      interval '1' hour
        * case priority_code when 'GC04' then 1 when 'GC05' then 2 when 'GC06' then 4 end
    )
    +
    -- actual time adjustment
    (
      -- possible time adjustment...
      (
        -- gap between 17:00 and 08:00
        interval '15' hour
        +
        -- weekend days, only if Friday
        (
            interval '2' day
              * case when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Fri'
                     then 1 else 0 end
        )
      )
      *
      -- ... but only if target exceeds 17:00
      case when extract
      (
        hour from logged_time
        +
        -- response time
        (
          interval '1' hour
            * case priority_code when 'GC04' then 1 when 'GC05' then 2 when 'GC06' then 4 end
        )
      ) > 16 then 1 else 0 end
    )
    as target_time
from your_table;

который с некоторыми примерами данных, такими как ваши, и перед вашими отсечками, как в пятницу, так и в понедельник, дает:

        ID PRIO LOGGED_TIME           TARGET_TIME          
---------- ---- --------------------- ---------------------
         1 GC06 2019-05-26 12:59:59.0 2019-05-26 16:59:59.0
         2 GC06 2019-05-26 13:15:00.0 2019-05-27 08:15:00.0
         3 GC05 2019-05-26 14:59:59.0 2019-05-26 16:59:59.0
         4 GC05 2019-05-26 15:15:00.0 2019-05-27 08:15:00.0
         5 GC04 2019-05-26 15:59:59.0 2019-05-26 16:59:59.0
         6 GC04 2019-05-26 16:15:00.0 2019-05-27 08:15:00.0
         7 GC06 2019-05-31 12:59:59.0 2019-05-31 16:59:59.0
         8 GC06 2019-05-31 13:15:00.0 2019-06-03 08:15:00.0
         9 GC05 2019-05-31 14:59:59.0 2019-05-31 16:59:59.0
        10 GC05 2019-05-31 15:15:00.0 2019-06-03 08:15:00.0
        11 GC04 2019-05-31 15:59:59.0 2019-05-31 16:59:59.0
        12 GC04 2019-05-31 16:15:00.0 2019-06-03 08:15:00.0

Вы можете уменьшить дублирование с помощью CTE или встроенного представления:

select id, priority_code, logged_time,
  raw_target_time
    +
    -- actual time adjustment
    (
      -- possible time adjustment...
      (
        -- gap between 17:00 and 08:00
        interval '15' hour
        +
        -- weekend days, only if Friday
        (
            interval '2' day
              * case when to_char(logged_time, 'Dy', 'NLS_DATE_LANGUAGE=ENGLISH') = 'Fri'
                     then 1 else 0 end
        )
      )
      *
      -- ... but only if target exceeds 17:00
      case when extract (hour from raw_target_time) > 16 then 1 else 0 end
    )
    as target_time
from (
  select id, priority_code, logged_time,
    logged_time
    +
    -- response time
    (
      interval '1' hour
        * case priority_code when 'GC04' then 1 when 'GC05' then 2 when 'GC06' then 4 end
    )
    as raw_target_time
  from your_table
);

и, конечно, это не нужно выкладывать так, я просто пытался немного прояснить логику.

0 голосов
/ 02 июня 2019

задания можно регистрировать в любое время суток с помощью онлайн-форм, а не только с 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

Возможно, вам следует исправить этот существующий код, а не пытаться обманутьрезультат, который он вам дает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...