SQL

Merging overlapping date ranges

Collapsing overlapping periods into continuous ranges: a new group is detected when a start exceeds the running max of the previous ends, then you aggregate per group.

Prerequisites

PostgreSQL, SQL Server 2012+

SQL
WITH ordered AS (
    SELECT *,
           MAX(end_date) OVER (
               ORDER BY start_date
               ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING
           ) AS prev_max_end
    FROM reservations
), flagged AS (
    SELECT *,
           CASE WHEN prev_max_end IS NULL
                  OR start_date > prev_max_end
                THEN 1 ELSE 0 END AS new_group
    FROM ordered
), grouped AS (
    SELECT *, SUM(new_group) OVER (ORDER BY start_date) AS grp
    FROM flagged
)
SELECT MIN(start_date) AS merged_start, MAX(end_date) AS merged_end
FROM grouped
GROUP BY grp
ORDER BY merged_start;

Result

 merged_start | merged_end
--------------+------------
 2026-06-01   | 2026-06-09
 2026-06-12   | 2026-06-15
 2026-06-20   | 2026-06-28
(3 rows)   -- 7 réservations chevauchantes réduites à 3 plages
SQLIntervallesChevauchementWindow Functions

Related snippets

Back to the Data Lab