Given a table of groups of intersecting polygons as shown.
(https://i.stack.imgur.com/hlXs1.png) How can we select all the groups of polygons that intersect?
The following query, using recursion, gets some of the way there but it duplicates all the groups and groups with multiple overlaps duplicate polygons within the group.
WITH RECURSIVE cte AS (
SELECT id AS root_id,
id, ARRAY[id] AS path,
geom
FROM polygons
UNION ALL
SELECT cte.root_id,
t.id, path || t.id,
t.geom
FROM polygons AS t,
cte
WHERE t.id <> ALL(cte.path)
AND ST_Intersects(t.geom, cte.geom)
)
SELECT root_id, ARRAY_AG(id)
FROM cte
GROUP BY root_id
ORDER BY root_id
The resulting selection looks like this:
| root_id | array_agg |
|---|---|
| 1 | 1,2 |
| 2 | 2,1 |
| 3 | 3,4,5,6 |
| 4 | 4,3,5,6 |
| 5 | 5,4,6,3 |
| 6 | 6,5,4,3 |
| 7 | 7,8,9,9,8 |
| 8 | 8,7,9,9,7 |
| 9 | 9,7,8,8,7 |
| 10 | 10 |
As you will notice, selections with root_id 1 and 2 contain the same polygons and root_id 7, 8 and 9 all duplicate polygons within the group.
There's a function for exactly that, named exactly like that:
ST_ClusterIntersectingWin(). Added in PostGIS 3.4.0.Demo at db<>fiddle:
Inspecting some samples:
In PostGIS 2.3.0+ you can get the same result, although slightly slower, using the
ST_ClusterDBSCAN(geom,0,1)function suggested by @JGH:In 2.2.0 there's a bit more clunky
ST_ClusterIntersecting()that's spitting out collections.