PostGIS空间数据融合实践:高效合并与优化指南
在GIS桌面软件里泡久了的同学都知道,要做两个或多个地理数据的融合,直接用工具就好。ArcGIS、QGIS、SuperMap这些主流桌面端都有成熟的功能,比如QGIS的工具包里就有合并工具,随手就能用。
不过工作中总会遇到更灵活的场景——数据已经存到了PostGIS空间数据库里,用户可能随机抽几个空间数据要动态融合,这时候总不能每次都去手动点工具吧?用SQL查询来解决就舒服多了。比如某个需求里,需要把几个城市的空间数据融合成一份新数据供查询分析,PostGIS里常用的两个函数就是ST_Union()和ST_Collect()。
这两个东西乍一看差不多,但实际用起来差别不小。官网的介绍吧,说得不算特别透,所以咱们直接上实例,用实际的面数据和场景来跑一遍,看看它们到底怎么用、区别在哪。
一、ST_Union()简介
先看PostGIS里st_union的定义,有几个入参版本:
函数定义长这样:
CREATE OR REPLACE FUNCTION "public"."st_union"("geom1" "public"."geometry", "geom2" "public"."geometry")
RETURNS "public"."geometry" AS '$libdir/postgis-3', 'ST_Union'
LANGUAGE c IMMUTABLE STRICT
COST 10000
1、方法说明
跟Ja va的方法重载差不多,st_union有5个重载版本:
| 序号 | 方法 |
|---|---|
| 1 | st_union(geometry, geometry) |
| 2 | st_union(geometry, geometry, float8) |
| 3 | st_union(_geometry) |
| 4 | st_union(geometry) |
| 5 | st_union(geometry, float8) |
2、参数介绍
geometry是空间对象,float8表示数据精度。注意:st_union运算后的结果是合并输入几何体,并且会消除重叠部分,输出可能是原子几何、多重几何或几何集合。关键点就是合并并消除重叠。
二、ST_Collect()简介
再看st_collect的定义:
函数定义SQL:
CREATE OR REPLACE FUNCTION "public"."st_collect"("geom1" "public"."geometry", "geom2" "public"."geometry")
RETURNS "public"."geometry" AS '$libdir/postgis-3', 'LWGEOM_collect'
LANGUAGE c IMMUTABLE
COST 50
1、方法说明
| 序号 | 函数 | 说明 |
|---|---|---|
| 1 | geometry ST_Collect(geometry g1, geometry g2); | 接受两个输入几何 |
| 2 | geometry ST_Collect(geometry[] g1_array); | 接受几何图形数组 |
| 3 | geometry ST_Collect(geometry set g1field); | 接受几何图形行集的聚合函数 |
2、参数介绍
将几何收集(聚合)到几何集合中。结果是一个多*或一个GeometryCollection,取决于输入几何的类型相同还是不同(同构或异类)。输入几何图形在集合中保持不变。注意这里的用词是聚合,跟上面的合并,概念完全不同。
3、两者区别
光从字面看,“合并”和“聚合”有点接近,但在空间运算里差别很大。一句话概括:ST_Collect只是把几何图形收集到一块,不做任何修改;ST_Union则会合并重叠部分、在交点处拆分线串,溶解边界后可能返回单个几何。说白了,st_collect不改变数据本身,st_union会改变数据的几何形态。下面实战验证。
三、实际案例实践
用面数据来试。分两种情况:空间不重叠和空间重叠,看看两个函数不同空间关系下的结果。
1、不重叠融合
用PostGIS里的城市数据,对长株潭三个城市做融合。
biz_city表数据如下:
用st_union融合:
select st_asgeojson(st_union(geom)) from biz_city where city_name in ('长沙市','株洲市','湘潭市');
查询结果:
在QGIS里看:
很明显,三个城市已经完全融合,边界消失,形成了一个全新的面数据。
再看看st_collect的效果:
select st_asgeojson(st_collect(geom)) from biz_city where city_name in ('长沙市','株洲市','湘潭市');
QGIS展示结果:
虽然三个城市也合在一起了,但各自的边界还在,并没有真正融合。从geojson的type上也能看出区别。
结论:在不重叠的情况下,st_union和st_collect的结果视觉差别不大,但对数据是否改变来说,影响很大。
2、空间重叠融合
准备两份空间重叠的数据,用模拟数据来演示:
-- A 图
select ST_GeomFromGeoJSON('{"type":"Polygon","coordinates":[[[120.52757263183594,31.495432803134843],[120.59211730957031,31.31199502365151],[120.89012145996094,31.35950051982242],[120.74729919466666,31.483245492650792],[120.52757263183594,31.495432803134843]]]}')
-- B 图
select ST_GeomFromGeoJSON('{"type":"Polygon","coordinates":[[[120.74386596679688,31.487235582017444],[120.84548950195312,31.269747790889888],[121.01783752441405,31.378261512889125],[120.91827392578125,31.487821121636433],[120.74386596679688,31.487235582017444]]]}')
转成geojson在QGIS里看,这是A图:
B图:
两者叠加后的空间关系:
用st_union融合:
-- ST_Union在几何形状重叠的地方对其进行几何合并,并在相交处拆分线串。溶解边界时,它可能会返回单个几何。
select ST_Union (
ST_GeomFromGeoJSON('{"type":"Polygon","coordinates":[[[120.52757263183594,31.495432803134843],[120.59211730957031,31.31199502365151],[120.89012145996094,31.35950051982242],[120.52757263183594,31.495432803134843]]]}'),
ST_GeomFromGeoJSON('{"type":"Polygon","coordinates":[[[120.74386596679688,31.487235582017444],[120.84548950195312,31.269747790889888],[121.01783752441405,31.378261512889125],[120.91827392578125,31.487821121636433],[120.74386596679688,31.487235582017444]]]}')
)
用st_collect融合:
-- ST_Collect将几何形状聚合到一个集合中,而无需进行任何更改。
select ST_Collect (
ST_GeomFromGeoJSON('{"type":"Polygon","coordinates":[[[120.52757263183594,31.495432803134843],[120.59211730957031,31.31199502365151],[120.89012145996094,31.35950051982242],[120.74729919466666,31.483245492650792],[120.52757263183594,31.495432803134843]]]}'),
ST_GeomFromGeoJSON('{"type":"Polygon","coordinates":[[[120.74386596679688,31.487235582017444],[120.84548950195312,31.269747790889888],[121.01783752441405,31.378261512889125],[120.91827392578125,31.487821121636433],[120.74386596679688,31.487235582017444]]]}')
)
实验结果同样印证:st_collect对原始数据没有丝毫改变,而st_union则把重叠部分溶解了,改变了数据的边界和几何形态。
总结
到这里应该真正理解了“合并”和“聚合”的区别。在实际项目里,根据需求选对函数非常关键:如果只需要把多个几何图形拼在一起、保留各自边界,用ST_Collect;如果需要消除重叠、生成一个连续完整的图形,就用ST_Union。选错了,结果可能差得很远。













