Сначала попробуйте сами: на собеседовании подсказки не будет.
Классический «gaps and islands». Сортируем периоды по началу и для каждого смотрим максимальный конец среди всех предыдущих: max(end_date) OVER (... ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING). Если текущий период начинается позже этого максимума, начинается новый остров.
Признак нового острова суммируем накопительно, получаем номер острова, и по нему берём min(start_date) и max(end_date). Сравнение именно с максимумом, а не с концом предыдущей строки: короткий период внутри длинного иначе разорвал бы остров.
WITH ordered AS (SELECT start_date, end_date, max(end_date) OVER (ORDER BY start_date, end_date ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) AS prev_max FROM reservations), flagged AS (SELECT start_date, end_date, CASE WHEN prev_max IS NULL OR start_date > prev_max THEN 1 ELSE 0 END AS new_grp FROM ordered), grouped AS (SELECT start_date, end_date, sum(new_grp) OVER (ORDER BY start_date, end_date) AS grp FROM flagged) SELECT min(start_date) AS start_date, max(end_date) AS end_date FROM grouped GROUP BY grp ORDER BY 1