如何在PostgreSQL(PostGIS)中找出仅点接触的不重复多边形对
解决PostGIS中仅单点接触的多边形对(无重复)问题
嘿,这个需求我熟!你已经搭好了基础的CTE框架,现在就差最后一步去掉重复的反向对,而且咱们还可以从源头优化,避免生成多余的结果行。
方法一:从源头避免重复(推荐,性能更优)
直接在关联的时候用a.id < b.id代替a.id != b.id,这样就不会生成(cn2, cn1)这种反向的重复对,从一开始就保证每对只出现一次:
WITH kms AS ( SELECT a.county AS cn1, b.county AS cn2, -- 可选:把接触点也查出来,方便后续验证 ST_Intersection(a.geom, b.geom) AS touch_point FROM spatial.us_counties AS a JOIN spatial.us_counties AS b ON ST_Touches(a.geom, b.geom) AND a.id < b.id -- 核心逻辑:避免生成反向重复对 AND ST_GeometryType(ST_Intersection(a.geom, b.geom)) = 'ST_Point' ) SELECT cn1, cn2, touch_point FROM kms;
方法二:对已有CTE结果去重
如果不想修改原CTE结构,也可以在后续查询里通过比较名称(或ID)的顺序来过滤重复:
WITH kms AS ( SELECT a.county AS cn1, b.county AS cn2, a.id AS id1, b.id AS id2 FROM spatial.us_counties AS a, spatial.us_counties AS b WHERE ST_Touches(a.geom, b.geom) = 'true' AND a.id != b.id AND ST_GeometryType(ST_Intersection(a.geom,b.geom)) = 'ST_Point' ) SELECT cn1, cn2 FROM kms t1 WHERE t1.id1 < t1.id2 -- 用ID比用名称更可靠(避免重名 county) GROUP BY t1.cn1, t1.cn2;
额外注意点
- 关于
ST_GeometryType:如果两个多边形通过多个离散点接触,ST_Intersection会返回ST_MultiPoint,这个条件会自动排除这类情况,刚好符合你“仅通过单个点接触”的需求。 - 性能优化:一定要确保
us_counties表的geom字段创建了空间索引(CREATE INDEX idx_us_counties_geom ON spatial.us_counties USING GIST(geom);),不然数据量大时关联查询会非常慢。 - 结果验证:可以把接触点字段保留,导入GIS工具可视化,确认确实是单个点接触的多边形对。
内容的提问来源于stack exchange,提问作者braveoldworld
相关产品推荐
相关产品推荐

