Вы можете генерировать диапазоны, используя функцию отведения:
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.