деление периода по временному интервалу - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть таблица, которая содержит несколько периодов времени, представляющих 'person-career', в той же таблице у меня есть все прерывания, связанные с одним и тем же человеком (т.е. holidays, illnesses ...).

используемый порядок в таблице (заказ по codeMission, затем год, затем сначала рабочий тип, затем второй праздничный период)

 Date begin Date end   Type    codeMission  year  name
 ---------- --------------------------------------------
 2001-01-01 2001-12-31 Working     Tx100     2001  James
 2001-05-01 2001-05-12 holidays    Tx100     2001  James

Я бы хотел разделить рабочий период на время праздников

 Date begin Date end   Type    codeMission  year  name
 ---------- -----------------------------------------
 2001-01-01 2001-04-30 Working    Tx100     2001  James
 2001-05-01 2001-05-12 holiday    Tx100     2001  James
 2001-05-13 2001-12-31 Working    Tx100     2001  James

Есть ли общий способ сделать это? Как вы знаете, время отпусков / болезней может быть иногда раньше или позже.

вопрос 1: Как я могу получить этот формат со всеми столбцами ? и есть конкретное, что я хотел бы упомянуть здесь, вопрос 2: когда период отпусков определяется на два года . Пример:

Date begin Date end   Type    codeMission  year  name
 ---------- --------------------------------------------
 2001-01-01 2001-12-31 Working     Tx100     2001  James
 2001-10-11 2002-04-30 holidays    Tx100     2001  James
 2002-01-01 2001-12-31 Working     Tx100     2002  James

здесь мы получим несколько вопросов !!! разделенные периоды не верны !! что ты делаешь?

1 Ответ

0 голосов
/ 06 ноября 2018

Это довольно сложно. Идея состоит в том, чтобы «разворачивать» даты и следить за тем, чтобы type входил или выходил каждый день. Затем вы можете использовать накопительные суммы, чтобы отслеживать фактический тип.

Итак:

with t as (
      select date '2001-01-01' as sdate, date '2001-12-31' as edate, 'Working' as type from dual union all
      select date '2001-05-01' as sdate, date '2001-05-12' as edate, 'holidays' from dual
     ),
     d as (
      select sdate as dte, type, 1 as flag from t union all
      select edate + 1, type, -1 as flag from t
     )
select d.dte, lead(dte) over (order by dte) - 1 as enddte,
       (case when flag = -1 then lag(type) over (partition by grp order by dte) else type end) as type
from (select d.*, sum(flag) over (order by dte) as grp
      from d
     ) d
order by dte;

Здесь - это дБ <> скрипка.

EDIT:

Здесь - улучшенная версия:

with t as (
      select date '2001-01-01' as sdate, date '2001-12-31' as edate, 'Working' as type from dual union all
      select date '2001-05-01' as sdate, date '2001-05-12' as edate, 'holidays' from dual union all
      select date '2001-07-01' as sdate, date '2001-08-12' as edate, 'holidays' from dual
     ),
     d as (
      select sdate as dte from t union all
      select edate + 1 from t
     )
select d.dte, d.enddte,
       (select max(t2.type) keep (dense_rank first order by t2.sdate desc)
        from t t2
        where t2.sdate <= d.dte and t2.edate >= d.enddte
       ) as type 
from (select d.*, lead(dte) over (order by dte) - 1 as enddte
      from d
     ) d
where dte <= enddte
order by d.dte

Этот подход просто получает отдельные периоды (разбивая первоначальные периоды). Затем для каждого периода он находит type, действительный в течение этого периода. Это самая последняя запись, охватывающая весь период.

Обратите внимание, что поскольку даты являются "смежными", частичное покрытие периодов отсутствует.

...