Вы можете сделать что-то вроде этого:
select id, min(entry_date) as start_date, max(entry_date) as end_date
from (
select id,
entry_date,
entry_date - (row_number() over(partition by id order by entry_date))::int as grp
from the_table
) t
group by id, grp
having max(entry_date) - min(entry_date) > 1
order by id, grp
Выражение entry_date - (row_number() over(partition by id order by entry_date))::int
создает одно значение DATE для всех последовательных «групп». Таким образом, внутренний запрос возвращает следующий результат (на основе данных примера):
id | entry_date | grp
---+------------+-----------
1 | 2018-05-03 | 2018-05-02
1 | 2018-07-13 | 2018-07-11
5 | 2018-06-10 | 2018-06-09
5 | 2018-07-14 | 2018-07-12
5 | 2018-07-15 | 2018-07-12
5 | 2018-07-16 | 2018-07-12
5 | 2018-07-17 | 2018-07-12
6 | 2018-06-11 | 2018-06-10
Группируя результат по этой дате (grp
), мы сохраняем эти даты вместе в одной группе. Мин и макс затем определяют начало и конец последовательного списка значений. После этого в предложении Имеются только те, чей диапазон превышает один день.
, который затем возвращает:
id | start_date | end_date
---+------------+-----------
5 | 2018-07-14 | 2018-07-17
Онлайн-пример