Это типичная проблема пробелов и островков.
Вот один подход, использующий оконные функции:
select
item,
min(available_date) min_available_date,
max(available_date) max_available_date,
count(*) no_days
from (
select
t.*,
sum(case when available_date = lag_available_date + interval '1' day then 0 else 1 end)
over(
partition by item
order by available_date
rows between unbounded preceding and current row
) grp
from (
select
t.*,
lag(available_date)
over(partition by item order by available_date) lag_available_date
from mytable t
) t
) t
group by item, grp
order by item, min_available_date
Самый внутренний запрос восстанавливает дату «предыдущей» записи. На следующем уровне сумма окна увеличивается на 1
каждый раз, когда даты не являются последовательными: это определяет группы. Затем внешний запрос агрегирует по группам.
Демонстрация по БД Fiddle
Пример данных:
item | available_date
:--- | :-------------
ABA | 2019-01-04
ABA | 2019-01-05
ABA | 2019-01-06
ABA | 2019-01-07
ABA | 2019-01-12
ABA | 2019-01-15
ABA | 2019-01-16
ABA | 2019-01-17
ABA | 2019-01-19
ABA | 2019-01-21
ABA | 2019-01-22
Запрос результаты:
item | min_available_date | max_available_date | no_days
:--- | :----------------- | :----------------- | ------:
ABA | 2019-01-04 | 2019-01-07 | 4
ABA | 2019-01-12 | 2019-01-12 | 1
ABA | 2019-01-15 | 2019-01-17 | 3
ABA | 2019-01-19 | 2019-01-19 | 1
ABA | 2019-01-21 | 2019-01-22 | 2