ST_Union可合并多个Point为去重后的MULTIPOINT或POINT,需配合GROUP BY分组聚合,注意SRID一致性和拓扑有效性,避免误用ST_Collect。

用 ST_Union 合并多个 Point 为一个 Geometry
PostgreSQL 本身不直接支持几何对象的“加法”聚合,但 PostGIS 提供了 ST_Union —— 它是处理空间聚合最常用、也最可靠的函数。对一组 POINT 类型的 geom 列,ST_Union 会自动合并重合点、去重,并返回一个拓扑有效的几何对象(通常是 MULTIPOINT 或单个 POINT)。
常见错误是直接套用 ST_Collect:它只是把所有点无脑打包成 MULTIPOINT,哪怕坐标完全一样也不会去重;而 ST_Union 会真正做几何融合。
- 正确写法:
SELECT ST_Union(geom) FROM locations WHERE type = 'poi'; - 如果必须确保输出是
MULTIPOINT(哪怕只剩一个点),再包一层ST_Multi():ST_Multi(ST_Union(geom)) -
ST_Union对空输入(零行)返回NULL,不是空几何,注意业务逻辑是否要COALESCE(..., ST_GeomFromText('MULTIPOINT EMPTY'))
GROUP BY 场景下聚合每个分组的几何对象
当需要按类别(如 category 或 region_id)分别合并点时,ST_Union 必须配合 GROUP BY 使用,且不能放在子查询里漏掉分组键。
容易踩的坑是误用窗口函数或忘记 GROUP BY 导致聚合跨组:PostgreSQL 会报错 column "x" must appear in the GROUP BY clause,但有时因别名或隐式引用掩盖问题。
- 安全写法:
SELECT category, ST_Multi(ST_Union(geom)) AS multipoint FROM places GROUP BY category; - 若某组只有 1 个点,
ST_Union返回POINT;加ST_Multi可强制统一为MULTIPOINT,避免下游解析失败 - 性能提示:确保
geom列上有GIST索引,否则ST_Union在大数据量下会显著变慢
合并线或面时要注意拓扑有效性
ST_Union 对 LINESTRING 或 POLYGON 的聚合不只是“拼起来”,它会尝试缝合相交边界、消除重叠、修复自相交 —— 这既是优势,也是风险点。
例如两条首尾相接的线段,ST_Union 可能合并为一条更长的线;两个相邻多边形可能融合成一个带孔的多边形。如果你只需要原始几何的集合而不做拓扑计算,该用 ST_Collect。
- 要保留原始结构、不做融合 → 用
ST_Collect(geom)(返回GEOMETRYCOLLECTION) - 要真正合并重叠/相邻区域 → 用
ST_Union(geom),但需确认结果是否符合业务语义 - 遇到
TopologyException错误(如 “Ring Self-intersection”),说明输入几何本身无效,先用ST_MakeValid(geom)预处理
聚合前务必检查 SRID 和坐标系一致性
PostGIS 要求参与 ST_Union 的所有几何对象具有相同 SRID。混用 WGS84(SRID=4326)和 Web Mercator(SRID=3857)会导致静默失败或错误结果,且 PostgreSQL 不报类型错误,只返回 NULL 或异常几何。
最常被忽略的是从不同表 JOIN 后未显式转换 SRID —— 比如一个表用 geography 类型存经纬度,另一个用 geometry 存投影坐标。
- 查当前 SRID:
SELECT ST_SRID(geom), COUNT(*) FROM mytable GROUP BY 1; - 统一转为 4326:
ST_Transform(geom, 4326)(仅适用于已有 SRID 的 geometry) - 若列无 SRID,必须先用
ST_SetSRID(geom, 4326)显式设定,否则ST_Union可能出错或结果不可靠

















