SQL Server中如何将邻近地理点聚类为多边形?
解决方案:SQL Server 空间点聚类为多边形簇
方法一:基于缓冲区相交的连通性聚类
完全贴合你的思路,通过生成缓冲区、识别相交对、构建连通簇,最后合并缓冲区得到簇多边形。
步骤与代码
假设你的表名为PointData,shape列是geography类型,聚类距离阈值为100米:
WITH BufferCTE AS ( -- 为每个点生成指定距离的缓冲区 SELECT id, shape.STBuffer(100) AS buffer_geo FROM PointData ), IntersectionPairs AS ( -- 找出所有相交的缓冲区对(避免重复配对) SELECT b1.id AS id1, b2.id AS id2 FROM BufferCTE b1 JOIN BufferCTE b2 ON b1.id < b2.id WHERE b1.buffer_geo.STIntersects(b2.buffer_geo) = 1 ), ClusterCTE AS ( -- 递归识别连通的簇:初始每个点自成一簇 SELECT id AS point_id, id AS cluster_id FROM BufferCTE UNION ALL -- 合并与当前簇相交的其他点到同一簇 SELECT c.point_id, ip.id2 AS cluster_id FROM ClusterCTE c JOIN IntersectionPairs ip ON c.cluster_id = ip.id1 WHERE c.point_id <> ip.id2 UNION ALL SELECT c.point_id, ip.id1 AS cluster_id FROM ClusterCTE c JOIN IntersectionPairs ip ON c.cluster_id = ip.id2 WHERE c.point_id <> ip.id1 ), FinalClusters AS ( -- 为每个点确定唯一的簇ID(取连通组件中最小的ID作为标识) SELECT point_id, MIN(cluster_id) AS cluster_id FROM ClusterCTE GROUP BY point_id ) -- 合并同一簇内的所有缓冲区,生成最终的簇多边形 SELECT fc.cluster_id, geography::UnionAggregate(b.buffer_geo) AS cluster_polygon FROM FinalClusters fc JOIN BufferCTE b ON fc.point_id = b.id GROUP BY fc.cluster_id;
方法二:使用SQL Server内置空间聚类函数(推荐)
SQL Server 2017及以上版本提供了STClusterDBSCAN函数,专门用于基于密度的空间聚类,性能比手动递归处理更优。
步骤与代码
该函数直接根据点之间的距离聚类,再对簇内点生成缓冲区并合并:
WITH PointClusters AS ( -- 对所有点进行DBSCAN聚类:100米为邻域半径,最小1个点即可成簇 SELECT id, shape, shape.STClusterDBSCAN(100, 1) OVER () AS cluster_id FROM PointData ), BufferCTE AS ( -- 为每个点生成缓冲区 SELECT cluster_id, shape.STBuffer(100) AS buffer_geo FROM PointClusters ) -- 合并同一簇的缓冲区 SELECT cluster_id, geography::UnionAggregate(buffer_geo) AS cluster_polygon FROM BufferCTE GROUP BY cluster_id;
注意事项
geography类型的STBuffer单位为米(基于WGS84坐标系),请根据实际需求调整距离值。- 两种方法的聚类逻辑差异:方法一通过缓冲区相交(点间距≤2倍缓冲区距离)聚类;方法二直接基于点间距聚类,若要和方法一逻辑对齐,需将
STClusterDBSCAN的距离参数设为200米。 - 若数据量较大,优先使用
STClusterDBSCAN,其底层优化过的算法性能远高于手动递归。
内容的提问来源于stack exchange,提问作者steve
相关产品推荐
相关产品推荐

