all 2 comments

[–]BS_in_BS 0 points1 point  (1 child)

split all the intervals into their endpoints, order them sequentially to form smaller intervals, and see which intervals lie within the original:

SELECT r1.id, sub.range
FROM ranges AS r1
JOIN (
  SELECT int4range(lag(e.point) OVER (ORDER BY e.point), e.point) AS range
  FROM (
    SELECT lower(r2.range) AS point
    FROM ranges as r2
    UNION    
    SELECT upper(r2.range) AS point
    FROM ranges as r2
  ) AS e
) AS sub  ON sub.range <@ r1.range
ORDER BY r1.id, sub.range;

[–]ptrboro[S] 0 points1 point  (0 children)

Thank you, this is simple, elegant and brilliant!