sql server不支持对geography/geometry列直接使用count、sum等常规聚合函数,仅原生支持stunionaggregate地理聚合方法,用于合并空间实例;主流做法是按行政区字段分组统计或通过stcontains关联区域表实现业务维度聚合,且必须确保srid一致。

SQL Server 本身不支持直接对 geography 或 geometry 类型列使用 COUNT、SUM 等常规聚合函数——你不能写 SELECT COUNT(GeogCol1) FROM table 来“统计地理对象”,也不能对坐标值做 AVG()。真正能用的聚合,是 SQL Server 提供的**静态地理聚合方法**(如 STUnionAggregate),或通过空间索引 + 关联区划表实现的**业务维度聚合**。
STUnionAggregate 是唯一原生地理聚合函数
这是 SQL Server 唯一内置的、专为 geography / geometry 设计的聚合方法,用于合并多个空间实例为一个几何体(例如把多个小区多边形合并成一个街道辖区)。它必须配合 GROUP BY 使用,且只接受单个空间列作为输入。
- 语法固定:
STUnionAggregate(geography_column),不能加条件、不能传参、不能与其他列混用 - 返回类型仍是
geography(或geometry),不是标量值;结果可能为空(如输入全为 NULL)或无效(如合并后自相交),需后续用STIsValid()检查 - 不支持并行执行,大数据量时性能明显下降;建议先用空间索引过滤再聚合
- 示例:合并同一城市的全部行政边界多边形
SELECT city_name, geography::STUnionAggregate(boundary_geom) AS merged_boundary FROM districts GROUP BY city_name
按行政区字段分组才是主流聚合方式
95% 的地理聚合需求其实不涉及空间运算,而是「把带坐标的记录,按省/市/网格等维度归类统计」。这时关键不是空间函数,而是如何让每条记录准确归属到某个区域。
- 优先用已有的标准行政区字段(如
province、adcode),确保值统一(比如全部用国家统计局最新编码,而非“广东”“广东省”混用) - 若只有经纬度,不要用
BETWEEN粗暴匹配范围——容易漏掉跨经度/纬度的边界点;改用STContains()+ 区域多边形表:SELECT g.name, COUNT(*) FROM locations l JOIN area_boundaries g ON g.geom.STContains(l.point_geom) = 1 GROUP BY g.name - 务必给
area_boundaries.geom和locations.point_geom创建空间索引,否则 JOIN 会退化为嵌套循环,千万级数据可能跑数小时
STDistance 不可直接聚合,但可间接用于热力分析
你不能写 AVG(geom1.STDistance(geom2)),因为 STDistance 是实例方法,不是标量函数。但可以通过子查询或 CTE 先算出距离,再聚合:
- 常见错误:在 SELECT 中直接调用
STDistance并试图和GROUP BY混用,会报错「无法对包含聚合或子查询的表达式执行聚合函数」 - 正确做法:先用 CROSS APPLY 或自连接生成距离列表,再对外层结果聚合
SELECT shop_id, AVG(dist_m) FROM ( SELECT s.id AS shop_id, u.id AS user_id, s.geom.STDistance(u.geom) AS dist_m FROM shops s CROSS APPLY users u ) d GROUP BY shop_id - 注意性能:CROSS APPLY 对 n×m 数据会生成笛卡尔积,生产环境必须加距离阈值过滤(如
WHERE s.geom.STDistance(u.geom) )
真正容易被忽略的是 SRID 一致性——所有参与空间计算的 geography 实例必须使用相同 SRID(通常是 4326),否则 STUnionAggregate 可能静默失败,STContains 返回错误结果,且这类错误不会抛异常,只会让聚合结果为空或逻辑错乱。











