Сравните даты между двумя датами в указанных c позициях - PullRequest
0 голосов
/ 01 мая 2020

Учитывая следующие примеры записей в таблице: MY_DATES , используя Oracle SQL и / или PL / SQL, мне всегда нужно брать первое DATE_Rurable в этой таблице, то есть 26 / 10/2019, а затем перейти к третьей записи / значению DATE_Rurable, т.е. 2/02/2020, и проверить, превышает ли разница между ними более 13 недель, т.е.

select to_date('2/02/2020','dd/mm/yyyy') - to_date('26/10/2019','dd/mm/yyyy') a from dual

Table Name: MY_DATES

NM  DATE_REGISTERED
--- ---------------
A1  26/10/2019
A1  2/11/2019
A1  2/02/2020
A1  9/02/2020
A1  16/02/2020
A1  23/02/2020
A1  1/03/2020
A1  8/03/2020

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

Ответы [ 2 ]

1 голос
/ 01 мая 2020

Вот эффективное решение, использующее предложение MATCH_RECOGNIZE, представленное в Oracle версии 12.1.

Предложение WITH имитирует входные данные (это не часть решения - удалите их и обратитесь к фактической таблице и имена столбцов в основном запросе).

Решение разделяет по NM и заказывает по DT, затем ищет три последовательные строки, где третья дата более 13 недель после первой. Как только он находит одно такое вхождение, он заполняет «шаблон совпадения» всеми оставшимися строками в разделе, по существу отбрасывая их - поскольку мы заботимся только об одном совпадении.

Обратите внимание на два NM I добавлено. У BB есть даты, с интервалом более 13 недель, но не в течение трех последовательных дат. CC имеет две последовательные даты с интервалом уже более 13 недель; CC нет в выводе, потому что нет трех разных дат для начала. (Обратите внимание - вот как я прочитал требование; если вместо этого нужно было указать «последовательные даты с интервалом более 13 недель», это можно легко решить - но это не формулировка в вопросе автора).

with
  my_dates (nm, date_registered) as (
    select 'A1', to_date('26/10/2019', 'dd/mm/yyyy') from dual union all
    select 'A1', to_date( '2/11/2019', 'dd/mm/yyyy') from dual union all
    select 'A1', to_date( '2/02/2020', 'dd/mm/yyyy') from dual union all
    select 'A1', to_date( '9/02/2020', 'dd/mm/yyyy') from dual union all
    select 'A1', to_date('16/02/2020', 'dd/mm/yyyy') from dual union all
    select 'A1', to_date('23/02/2020', 'dd/mm/yyyy') from dual union all
    select 'A1', to_date( '1/03/2020', 'dd/mm/yyyy') from dual union all
    select 'A1', to_date( '8/03/2020', 'dd/mm/yyyy') from dual union all
    select 'BB', to_date( '2/03/2019', 'dd/mm/yyyy') from dual union all
    select 'BB', to_date('14/03/2019', 'dd/mm/yyyy') from dual union all
    select 'BB', to_date('18/03/2019', 'dd/mm/yyyy') from dual union all
    select 'BB', to_date('10/06/2019', 'dd/mm/yyyy') from dual union all
    select 'BB', to_date( '3/04/2019', 'dd/mm/yyyy') from dual union all
    select 'CC', to_date('15/08 2019', 'dd/mm/yyyy') from dual union all
    select 'CC', to_date('15/02/2020', 'dd/mm/yyyy') from dual
  )
-- end of sample data (for testing only); query begins below this comment
select nm
from   my_dates
match_recognize(
  partition by nm
  order     by date_registered
  pattern   ( a b c x* )
  define    c as date_registered > a.date_registered + 91
);



NM
----
A1

** РЕДАКТИРОВАТЬ **

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

Это упрощает задачу. И решение может быть легко изменено - единственное необходимое изменение - это предложение pattern, оно должно выглядеть так:

pattern ( ^ a b c )

Это закрепляет поиск трех строк в начале раздела. Другие ряды не проверяются.

1 голос
/ 01 мая 2020

Это кажется странным. Я думаю lead() и lag). Если вы хотите, чтобы значения nm соответствовали условию:

select md.*
from (select md.*,
             lead(date_registered, 2) over (partition by nm order by date_registered) as next_dr_2,
             lag(date_registered) over (partition by nm order by date_registered) as prev_dr
      from my_dates md
     ) md
where prev_dr is null and
      next_dr_2 > date_registered + interval '91' day;
...