PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Finden Sie Zeilen mit angrenzenden Datumsbereichen und kumulieren Sie deren Dauer

Dies ist ein Lücken- und Inselproblem. In diesem Fall können Sie lag() verwenden um zu sehen, wo eine Insel beginnt und dann eine kumulierte Summe.

Die letzte Operation ist eine Aggregation (unter Verwendung von Fensterfunktionen):

SELECT p.*, 
      (Max(ends_on) OVER (PARTITION BY location_id, grp) - Min(starts_on) OVER (PARTITION BY location_id, grp) ) + 1 AS duration,
      Array_agg(p.id) OVER (PARTITION BY location_id) 
FROM (SELECT p.*, 
             Count(*) FILTER (WHERE prev_eo < starts_on - INTERVAL '1 day') OVER (PARTITION BY location_id ORDER BY starts_on) AS grp
      FROM (SELECT id, starts_on, ends_on, location_id, holiday_or_vacation_type_id, 
                   lag(ends_on) OVER (PARTITION BY location_id ORDER BY (starts_on)) AS prev_eo
            FROM periods 
           ) p
     ) p;