Dies ist eine Form von Lücken und Inseln. Bestimmen Sie in diesem Fall, wo die Inseln beginnen, indem Sie am Anfang nach Überschneidungen suchen. Führen Sie dann eine kumulative Summe der Starts und Aggregation durch:
select max(id), min(start), max(end), max(created_at)
from (select t.*,
count(*) filter (where max_end < end) over (order by start) as grouping
from (select t.*,
max(end) over (order by start rows between unbounded preceding and 1 preceding) as max_end
from events t
) t
) t
group by grouping;