Given a table of groups of intersecting polygons as shown.enter image description here(https://i.stack.imgur.com/hlXs1.png) How can we select all the groups of polygons that intersect?

下面的查询,使用递归,得到了一些方法,但它复制了所有的组和组内具有多个重叠重复多边形的组.

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

结果 Select 如下:

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

您会注意到,root_id 1和2的 Select 包含相同的多边形,root_id 7、8和9的所有多边形在组中重复.

推荐答案

There's a function for exactly that, named exactly like that: ST_ClusterIntersectingWin(). Added in PostGIS 3.4.0.
Demo at db<>fiddle:

enter image description here

explain analyze verbose 
create table my_shapes_clustered2 as
select 1+ST_ClusterIntersectingWin(geom)over() as cluster_number, *
from my_shapes;
QUERY PLAN
WindowAgg (cost=0.00..15091.00 rows=1200 width=391) (actual time=5.639..5.948 rows=1200 loops=1)
  Output: (1 + st_clusterintersectingwin(geom) OVER (?)), id, initial_seed, geom
  -> Seq Scan on public.my_shapes (cost=0.00..76.00 rows=1200 width=387) (actual time=0.006..0.215 rows=1200 loops=1)
        Output: geom, id, initial_seed
Planning Time: 0.063 ms
Execution Time: 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;
cluster_number st_area count array_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+中,你可以得到相同的结果,尽管速度稍慢,使用ST_ClusterDBSCAN(geom,0,1)函数suggested by @JGH:

explain analyze verbose 
create table my_shapes_clustered3 as
select 1+ST_ClusterDBSCAN(geom,0,1)over() as cluster_number, *
from my_shapes;
QUERY PLAN
WindowAgg (cost=0.00..15091.00 rows=1200 width=391) (actual time=17.688..18.018 rows=1200 loops=1)
  Output: (1 + st_clusterdbscan(geom, '0'::double precision, 1) OVER (?)), id, initial_seed, geom
  -> Seq Scan on public.my_shapes (cost=0.00..76.00 rows=1200 width=387) (actual time=0.005..0.218 rows=1200 loops=1)
        Output: geom, id, initial_seed
Planning Time: 0.041 ms
Execution Time: 21.007 ms

在2.2.0中,有一点笨重的ST_ClusterIntersecting(),吐出集合.

Sql相关问答推荐

当编号和版本的唯一状态更改时报告

SQL更新,在2个额外的表上使用内部连接

查询多个表并返回合并在联合列上的所有表中的所有行

我可以将INSERT语句与SELECT一起使用来创建条件吗?

连接特定行号

转换表中的数据

返回包含列和包含其他列的列表的自定义查询

如何在Presto中将多个列合并到一个数组中

用于从第二个表中提取具有最小最终价格值的记录的SQL查询

使用左外部联接更正列中第+1行的值时重复

如何使用jsonn_populate_record()插入到包含IDENTITY列的表中

对现有记录进行分组

匹配 H[0-9][0-9] 但不匹配除字母 H 之外的任何字母

如何从一张表中获取值在至少三行相同的记录

查询中获取审批者不起作用

String_Split 多列

雅典娜弄错了操作顺序

以 15 分钟为间隔的使用情况SQL 查询

在 Athena / Presto 中提取 JSON 对象以获取动态密钥

使用 json_agg 从 SQL 查询获取 [null] 响应