Определите фактическое TAT (время оборота), сравнив два столбца даты.

У меня есть таблица со следующей структурой, с помощью которой я пытаюсь найти TAT (время оборота) между двумя днями. Но, если совпадают дни, я не могу найти фактический ТАТ.

Appln No        Start Date  End Date
1001009     01-10-15    06-10-15
1001009     02-10-15    04-10-15
1001009     03-10-15    04-10-15
1001009     03-10-15    05-10-15
1001009     04-10-15    07-10-15
1001009     09-10-15    10-10-15
1001009     12-10-15    16-10-15
1001009     14-10-15    17-10-15

После удаления перекрывающихся дат из приведенных выше образцов данных выходные данные будут иметь следующий формат:

Appln No    Start Date  End Date
1001009     01-10-15    07-10-15
1001009     09-10-15    10-10-15
1001009     12-10-15    17-10-15

Поскольку я новичок в sql и использую разработчика oracle sql, мне сложно написать приведенную выше логику в коде. Любые предложения по этому вопросу приветствуются :)


person Manoj    schedule 21.10.2015    source источник


Ответы (3)


Попробуй это:

select t1.* from myTable t1
inner join myTable t2
on t2.StartDate > t1.StartDate and t2.StartDate < t1.EndDate
person Rahul Tripathi    schedule 21.10.2015
comment
Не будет работать, если для Appln есть только одна запись. - person JimmyB; 21.10.2015

Более того, сложная задача, так как вы не можете доверять какому-либо порядку интервалов. Я атакую ​​его, удаляя подинтервалы (интервалы, полностью покрытые другим интервалом). После этого я могу следовать порядку, определенному START_DATE, чтобы увидеть, перекрывается ли предыдущий интервал со следующим, и применить стандартный механизм группировки.

 with subs as (
 /* first remove all intervals that are subsets of other intervals */
 select * from tst t1
 where NOT exists (select null from tst t2 where t2.start_date < t1.start_date and t1.end_date < t2.end_date)
 ),overlap as (
 select APPLN_NO, START_DATE, END_DATE,
 case when (nvl(lag(END_DATE) over (partition by APPLN_NO order by START_DATE),START_DATE-1)  < START_DATE) then 
      row_number() over (partition by APPLN_NO order by START_DATE) end grp
 from subs),
 overlap2 as (
 select 
 APPLN_NO, START_DATE, END_DATE, GRP,
 last_value(grp ignore nulls) over (partition by APPLN_NO order by START_DATE) as grp2
 from overlap)
 select 
   APPLN_NO,   min(START_DATE) START_DATE, max(END_DATE) END_DATE
 from overlap2
 group by APPLN_NO, grp2
 order by 1,2
 ;

Для проверки запроса здесь моя настройка

 drop table tst ;
 create table tst 
 (appln_no number,
 start_date date,
 end_date date);

 insert into tst values (1001009, to_date('01-10-15','dd-mm-rr'),to_date('06-10-15','dd-mm-rr'));
 insert into tst values (1001009, to_date('02-10-15','dd-mm-rr'),to_date('04-10-15','dd-mm-rr'));
 insert into tst values (1001009, to_date('03-10-15','dd-mm-rr'),to_date('04-10-15','dd-mm-rr'));
 insert into tst values (1001009, to_date('03-10-15','dd-mm-rr'),to_date('05-10-15','dd-mm-rr'));
 insert into tst values (1001009, to_date('04-10-15','dd-mm-rr'),to_date('07-10-15','dd-mm-rr'));
 insert into tst values (1001009, to_date('09-10-15','dd-mm-rr'),to_date('10-10-15','dd-mm-rr'));
 insert into tst values (1001009, to_date('12-10-15','dd-mm-rr'),to_date('16-10-15','dd-mm-rr'));
 insert into tst values (1001009, to_date('13-10-15','dd-mm-rr'),to_date('14-10-15','dd-mm-rr')); /* this is added to make it more interesting */
 insert into tst values (1001009, to_date('15-10-15','dd-mm-rr'),to_date('17-10-15','dd-mm-rr'));

дайте

    APPLN_NO START_DATE          END_DATE          
 ---------- ------------------- -------------------
    1001009 01.10.2015 00:00:00 07.10.2015 00:00:00 
    1001009 09.10.2015 00:00:00 10.10.2015 00:00:00 
    1001009 12.10.2015 00:00:00 17.10.2015 00:00:00 

как и ожидалось.

person Marmite Bomber    schedule 21.10.2015
comment
Большое тебе спасибо. Я проверю это после того, как вернусь в свой офис. Хотя у меня есть одно сомнение. Этот запрос будет работать в Oracle SQL Developer, верно? До сих пор я не использовал «с сабвуферами как» ни в одном из моих запросов оракула. - person Manoj; 22.10.2015
comment
@Mathew, не беспокойтесь о факторинге подзапросов работает в Sql Developer как шарм. - person Marmite Bomber; 22.10.2015

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

Далее предполагается, что ваша таблица имеет первичный ключ (названный id из-за отсутствия лучшего имени).

Это дает возможность агрегировать, чтобы получить желаемое:

select ApplnNo, min(start), max(end)
from (select t.*,
             sum(IsGroupStart) over (partition by ApplnNo order by start) as grp
      from (select t.*,
                   (case when exists (select 1
                                      from t t2
                                      where t2.end >= t.start and t2.start <= t.end and
                                            t2.id <> t.id
                                     )
                         then 0 else 1
                    end) as IsGroupStart
            from t
           ) t
      ) t
group by ApplnNo, grp;

Есть некоторые нюансы. Точный самый внутренний подзапрос для exists зависит от того, как вы определяете перекрытия. Это включает в себя даже один день перекрытия в начале или конце.

person Gordon Linoff    schedule 21.10.2015
comment
Красивый и элегантный подход с использованием SUM вместо LAST_VALUE. Но я предполагаю, что условие в подзапросе должно быть where t2.end > t.start and t2.start < t.start вместо where t2.end >= t.start and t2.start <= t.end. 1) Для проверки перекрытия используется только день начала, т. е. рассматривается только левая сторона. 2) Хотя бы одно из условий должно быть меньше. В противном случае подзапрос возвращает всегда записи. - person Marmite Bomber; 21.10.2015
comment
@МармитБомбер . . . На самом деле, изменение неравенства не работает. Таблице нужен первичный ключ, чтобы предотвратить подсчет одной и той же записи. Действительно хороший улов. - person Gordon Linoff; 22.10.2015
comment
Спасибо @Gordon, я был близок к заполнению SR из-за неожиданного поведения :) - person Marmite Bomber; 22.10.2015
comment
Большое тебе спасибо. Я проверю это после того, как вернусь в свой офис. - person Manoj; 22.10.2015