By using db<>fiddle, you agree to license everything you submit by Creative Commons CC0.
Create Table tbl ( timeid INTEGER, starts INTEGER, ends INTEGER );
✓
Insert Into tbl VALUES
(1, 0, 10), (1, 2, 13), (1, 3, 15), (1, 11, 21), (1, 15, 30),
(2, 0, 10), (2, 2, 13), (2, 11, 21), (2, 15, 30);
✓
WITH
grid AS
( Select t.timeid, t.starts, t.ends,
( Select Max(starts) From tbl Where timeid = t.timeid And starts < t.starts ) as last_start,
( Select Max(ends) From tbl Where timeid = t.timeid And starts < t.starts ) as last_end,
t2.starts as starts_2, t2.ends as ends_2
From tbl t
Left Join tbl t2 ON( t2.timeid = t.timeid And
t2.starts > t.ends )
),
overlaps AS
( SELECT DISTINCT
g.timeid, g.starts, g.ends,
g2.starts as starts_overlap, g2.ends as ends_overlap,
Case When g2.starts < LAG(g2.ends) Over(Partition By g2.timeid Order By g2.starts)
Then 'OUT'
Else 'IN'
End as flag
FROM tbl t
INNER JOIN ( Select *
From grid
Where last_start Is Null OR starts > last_end
) g ON( ( g.timeid = t.timeid And g.starts = t.starts And g.ends = t.ends )
OR
( g.timeid = t.timeid And g.starts_2 = t.starts And g.ends_2 = t.ends )
)
LEFT JOIN grid g2 ON( g2.timeid = t.timeid And g2.starts > t.starts And g2.starts < t.ends )
ORDER BY t.timeid, t.starts
)
Select t.*
From overlaps o
Inner Join tbl t ON( t.timeid = o.timeid And
t.starts = Coalesce(o.starts_overlap, o.starts) And
t.ends = Coalesce(o.ends_overlap, o.ends) )
Where ( o.starts_overlap Is Null OR o.starts_overlap > o.ends ) And o.flag = 'IN'
Order By o.timeid, o.starts
timeid | starts | ends |
---|---|---|
1 | 0 | 10 |
1 | 15 | 30 |
2 | 0 | 10 |
2 | 15 | 30 |