Oracle рекурсивный запрос только с одним столбцом - PullRequest
0 голосов
/ 28 июня 2018

У меня есть таблица leg со столбцом даты datainizio, в котором есть строки:

23-MAR-18
15-MAR-13

Я должен подтвердить, что внешняя дата находится между sysdate и 23 марта 18 или 22 марта 18 и 15 марта 13. Эти даты взяты из таблицы par, в которой:

02-APR-18
04-MAR-17
17-MAR-16

Результат, который я пытаюсь получить:

range                   count
----------------------  -----
23-MAR-18 - sysdate         1
15-MAR-13 - 22-MAR-18       2

Можно ли сделать это с помощью рекурсии?

1 Ответ

0 голосов
/ 28 июня 2018

Вы можете генерировать диапазоны, используя функцию отведения:

select datainizio as date_from,
  coalesce(lead(datainizio) over (order by datainizio), sysdate) as date_to
from leg;

DATE_FROM  DATE_TO   
---------- ----------
2013-03-15 2018-03-23
2018-03-23 2018-06-28

, а затем обработайте его как CTE и используйте левое внешнее объединение с таблицей par для подсчета совпадений на основе диапазона:

with ranges as (
  select datainizio as date_from,
    coalesce(lead(datainizio) over (order by datainizio), sysdate) as date_to
  from leg
)
select r.date_from, r.date_to - 1/86400 as date_to, count(p.datainizio)
from ranges r
left join par p
on p.datainizio >= r.date_from
and p.datainizio < r.date_to
group by r.date_from, r.date_to
order by r.date_from;

DATE_FROM  DATE_TO    COUNT(P.DATAINIZIO)
---------- ---------- -------------------
2013-03-15 2018-03-22                   2
2018-03-23 2018-06-28                   1

Я корректирую значение date-to на секунду, чтобы получить значения (кроме sysdate), которые были накануне. Если все даты par имеют время как полночь, вы можете сделать это в CTE, взяв там один день. (Это также предполагает, что сегодня он будет работать после полуночи).

Если вы хотите видеть диапазоны в виде строк, как вы показали, с sysdate в качестве слова, вы можете немного изменить CTE и использовать конкатенацию строк:

with ranges as (
  select datainizio as date_from,
    lead(datainizio) over (order by datainizio) as date_to
  from leg
)
select to_char(r.date_from, 'DD-MON-RR') || ' - ' ||
  case when date_to is null then 'sysdate'
       else to_char(date_to - 1/86400, 'DD-MON-RR')
  end as range,
  count(p.datainizio)
from ranges r
left join par p
on p.datainizio >= r.date_from
and p.datainizio < coalesce(r.date_to, sysdate)
group by r.date_from, r.date_to
order by r.date_from;

RANGE                 COUNT(P.DATAINIZIO)
--------------------- -------------------
15-MAR-13 - 22-MAR-18                   2
23-MAR-18 - sysdate                     1

ДБ <> Fiddle demo.

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