给定如图所示的相交多边形组表。()我们如何选择所有相交的多边形组?
以下查询使用递归,获得了一些结果,但它复制了所有组以及组内具有多个重叠重复多边形的组。
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
最终的选择如下所示:
root_id | 数组_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 |
您将注意到,
root_id
1 和 2 的选择包含相同的多边形,root_id
7、8 和 9 包含组内所有重复的多边形。
ST_ClusterIntersectingWin()
完全一样。explain analyze verbose
create table my_shapes_clustered2 as
select 1+ST_ClusterIntersectingWin(geom)over() as cluster_number, *
from my_shapes;
查询计划 |
---|
WindowAgg(成本=0.00..15091.00行=1200宽度=391)(实际时间=5.639..5.948行=1200循环=1) |
输出:(1 + st_clusterintersectingwin(geom) OVER (?)), id, initial_seed, geom |
-> public.my_shapes 上的顺序扫描(成本=0.00..76.00 行=1200 宽度=387)(实际时间=0.006..0.215 行=1200 循环=1) |
输出:geom,id,initial_seed |
规划时间:0.063毫秒 |
执行时间:8.455 ms |
select cluster_number,st_area(st_union(geom)),count(*),array_agg(id)
from my_shapes_clustered2
group by cluster_number
order by cluster_number
limit 8;
簇号 | st_区域 | 数 | 数组_agg |
---|---|---|---|
1 | 836.248837776196 | 2 | {798,1} |
2 | 651.4061064388445 | 1 | {2} |
3 | 53.56050595625381 | 1 | {3} |
4 | 269.4408305746047 | 1 | {4} |
5 | 1596.5821681225993 | 4 | {507,5,676,72} |
6 | 1262.1100035153077 | 3 | {186,296,6} |
7 | 2008.7632476757103 | 4 | {474,891,7,1121} |
8 | 66.289777695502 | 1 | {8} |
在 PostGIS 2.3.0+ 中,使用@JGH建议的
ST_ClusterDBSCAN(geom,0,1)
函数,可以获得相同的结果,尽管速度稍慢:
explain analyze verbose
create table my_shapes_clustered3 as
select 1+ST_ClusterDBSCAN(geom,0,1)over() as cluster_number, *
from my_shapes;
ST_ClusterIntersecting()
,即吐出集合。