SheepDog1998

博客园 首页 新随笔 联系 订阅 管理

PostGIS 核心函数手册

 
必记基础
 
  • geometry:平面几何,单位度,不准
  • geography:地球球面,单位米,真实距离
  • 业务 99% 必须用 geography
 
 

 

一、空间对象创建(基础必学)

 

1. ST_MakePoint

 
作用:经纬度 → 数据库可识别的空间点
 
基础语法
ST_MakePoint(经度, 纬度)
 
 
示例
-- 创建北京中心点的空间点
SELECT ST_MakePoint(116.40, 39.90);
 
查询结果
 
POINT(116.40 39.90) 点对象
 
业务场景
 
接收前端用户定位、商家坐标、设备 GPS,转换成 PostGIS 可计算的点。
 
使用注意事项
 
  • 必须严格遵循「经度在前,纬度在后」的顺序,颠倒会导致坐标定位到海外;
  • 生成的点无坐标系,仅能作为基础对象,需配合 ST_SetSRID 绑定坐标系后才能参与空间计算;
  • 可通过 ST_X(geom)/ST_Y(geom) 反向提取经纬度数值。
 

 

2. ST_SetSRID

 
作用:给空间对象绑定坐标系(核心为 4326)
 
基础语法
ST_SetSRID(几何对象, 坐标系编号)
 
示例
-- 给北京中心点绑定4326坐标系
SELECT ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326);
 
查询结果
 
带坐标系的点:SRID=4326;POINT(116.40 39.90)
 
业务场景
 
让坐标具备真实地理意义,用于距离、范围、包含关系计算。
 
使用注意事项
 
  • 无 SRID 的空间对象无法进行有效地理计算,所有参与业务的空间对象必须绑定 SRID;
  • 常用 SRID:4326(WGS84,用于距离 / 范围计算)、3857(墨卡托投影,用于前端地图展示);
  • 批量修复无 SRID 数据时,需先通过 ST_SRID(geom) 筛选出 SRID=0 的记录,避免重复绑定。
 

 

3. ST_GeomFromText

 
作用:WKT 文本 → 点 / 线 / 面对象
 
基础语法
ST_GeomFromText(WKT文本, 坐标系编号)
 
示例
 
-- 示例1:创建点
SELECT ST_GeomFromText('POINT(116.40 39.90)', 4326);
-- 示例2:创建北京到天津的路线
SELECT ST_GeomFromText('LINESTRING(116.40 39.90, 117.20 39.13)', 4326);
-- 示例3:创建简单的多边形区域
SELECT ST_GeomFromText('POLYGON((116.40 39.90, 116.50 39.90, 116.50 39.80, 116.40 39.90))', 4326);
 
 
查询结果
 
返回对应点、线、面空间对象。
 
业务场景
 
外部 GIS 数据导入、手动构造区域、接口参数解析。
 
使用注意事项
 
  • WKT 文本中坐标必须用空格分隔,不可用逗号;
  • 多边形需保证闭合(最后一个点与第一个点重合),否则会报错;
  • 反向输出空间对象为 WKT 文本可使用 ST_AsText(geom),便于数据导出 / 前端展示。
 

 

4. ST_MakeLine

 
作用:多个点 → 一条线(轨迹 / 路线)
 
基础语法
 
-- 手动拼接
ST_MakeLine(点对象1, 点对象2, ...)
-- 从表中拼接
ST_MakeLine(geom ORDER BY 排序字段)
 
 
示例
 
-- 示例1:手动拼接北京到上海的路线
SELECT ST_MakeLine(
  ST_MakePoint(116.40, 39.90),
  ST_MakePoint(121.47, 31.23)
);
-- 示例2:从表中拼接用户GPS轨迹
SELECT ST_MakeLine(geom ORDER BY gps_time) AS track_line
FROM gps_data 
WHERE user_id = '1001' AND gps_date = '2026-02-25';
 
 
查询结果
 
线对象
 
业务场景
 
用户 GPS 轨迹拼接、车辆行驶路线、公交 / 地铁线路、配送路径。
 
使用注意事项
 
  • 从表中拼接时必须指定排序字段(如时间),否则路线会错乱;
  • 需先过滤表中 geom IS NULL 的记录,避免轨迹断裂;
  • 若存在重复 GPS 点,可通过 ST_MakeLine(DISTINCT geom ORDER BY ...) 去重后再拼接。
 

 

二、空间关系判断(业务核心)

 

1. ST_DWithin(你最常用)

 
作用:查询 指定距离内 的所有数据
 
基础语法
 
ST_DWithin(空间对象A, 空间对象B, 距离阈值, use_spheroid=true)
 
 
示例
 
-- 示例1:查询北京中心点10公里内的乡镇
SELECT province, city, county, town
FROM gsyj_gsxzbj
WHERE ST_DWithin(
  geom::geography,
  ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326)::geography,
  10000 -- 10公里(米)
);
-- 示例2:外卖场景-查询用户5公里内的商家
SELECT shop_name, address
FROM shop_info
WHERE ST_DWithin(
  shop_geom::geography,
  ST_SetSRID(ST_MakePoint(116.38, 39.92), 4326)::geography,
  5000
);
 
 
查询结果
 
指定距离内的商家、网点、设备、乡镇列表。
 
业务场景
 
附近门店、外卖配送范围、就近派单、电子围栏、周边 POI 检索。
 
使用注意事项
 
  • 必须将 geometry 类型转为 geography(::geography),否则距离单位为 “度”,结果完全错误;
  • 距离阈值单位为米,需提前完成公里→米的转换(如 10 公里 = 10000 米);
  • 大数据量查询前,必须给 geom 字段创建 GIST 空间索引(CREATE INDEX idx_表名_geom ON 表名 USING GIST(geom);),否则查询极慢;
  • use_spheroid=false 可切换为球体计算,速度更快但精度略低,适合大范围低精度场景。
 

 

2. ST_Intersects

 
作用:判断两个空间对象是否相交 / 重叠
 
基础语法
 
ST_Intersects(空间对象A, 空间对象B)
 
 
示例
 
-- 示例1:判断长安街是否穿过朝阳区
SELECT ST_Intersects(
  (SELECT geom FROM road_info WHERE road_name = '长安街'),
  (SELECT geom FROM gsyj_gsxzbj WHERE county = '朝阳区' AND city = '北京市')
);
-- 示例2:查询洪水覆盖的农田
SELECT farm_id, farm_name
FROM farm_info
WHERE ST_Intersects(
  farm_geom,
  (SELECT flood_geom FROM flood_data WHERE flood_id = 'F001')
);
 
 
查询结果
 
true /false(单判断);符合条件的列表(范围查询)
 
业务场景
 
判断道路是否穿过行政区、洪水是否覆盖农田、线路是否穿越保护区。
 
使用注意事项
 
  • 只要两个对象有任意一点重叠,即返回 true,需注意 “边界接触” 也判定为相交;
  • 若需判断 “完全不相交”,可使用反向函数 ST_Disjoint(A,B)
  • 参与计算的两个对象需统一坐标系,否则可能出现误判。
 

 

3. ST_Contains

 
作用:判断 A 完全包含 B
 
基础语法
 
ST_Contains(包含方对象A, 被包含方对象B)
 
 
示例
 
-- 示例1:判断用户定位是否在海淀区内
SELECT ST_Contains(
  (SELECT geom FROM gsyj_gsxzbj WHERE county = '海淀区' AND city = '北京市'),
  ST_SetSRID(ST_MakePoint(116.30, 39.95), 4326)
);
-- 示例2:查询北京市下辖的所有乡镇
SELECT town
FROM gsyj_gsxzbj
WHERE ST_Contains(
  (SELECT geom FROM gsyj_gsxzbj WHERE city = '北京市' AND county = ''),
  geom
);
 
 
查询结果
 
true /false(单判断);符合条件的列表(范围查询)
 
业务场景
 
判断用户是否在某个城市 / 区内、商家是否在商圈内、点位是否在管控区内。
 
使用注意事项
 
  • 严格遵循 “包含方在前,被包含方在后” 的参数顺序,颠倒会导致结果错误;
  • 点落在对象 A 的边界上时,ST_Contains 返回 false,若需包含边界判断,需使用 ST_Covers
  • 可使用 ST_Within(B,A) 替代(效果一致),参数顺序更符合 “B 是否在 A 内” 的日常逻辑。
 

 

4. ST_Covers

 
作用:宽松包含(边界上也算)
 
基础语法
 
ST_Covers(覆盖方对象A, 被覆盖方对象B)
 
 
示例
 
-- 示例1:判断基站是否归属朝阳区(含边界)
SELECT ST_Covers(
  (SELECT geom FROM gsyj_gsxzbj WHERE county = '朝阳区'),
  (SELECT geom FROM base_station WHERE base_id = 'B001')
);
-- 示例2:批量判断边界点位的行政区划归属
SELECT point_id, ST_Covers(area_geom, point_geom) AS is_cover
FROM boundary_points, area_info
WHERE area_info.area_name = '朝阳区';
 
 
查询结果
 
true / false
 
业务场景
 
基站归属、边界点位归属、卡口 / 围栏边界判断。
 
使用注意事项
 
  • 参数顺序与 ST_Contains 一致,覆盖方在前,被覆盖方在后;
  • 反向判断可使用 ST_CoveredBy(B,A),效果与 ST_Covers(A,B) 完全一致;
  • 实际业务中优先使用 ST_Covers,可避免边界点 “归属模糊” 导致的数据遗漏。
 

 

三、距离 / 长度 / 面积计算

 

1. ST_Distance

 
作用:计算两点 / 两对象的真实球面距离
 
基础语法
 
ST_Distance(空间对象A, 空间对象B)
 
 
示例
 
-- 示例1:计算北京到上海的距离(公里)
SELECT ST_Distance(
  ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326)::geography,
  ST_SetSRID(ST_MakePoint(121.47, 31.23), 4326)::geography
) / 1000 AS distance_km;
-- 示例2:按距离排序查询10公里内的乡镇
SELECT town, ROUND(ST_Distance(geom::geography, ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326)::geography)/1000,1) AS km
FROM gsyj_gsxzbj
WHERE ST_DWithin(geom::geography, ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326)::geography, 10000)
ORDER BY km ASC;
 
 
查询结果
 
距离数值(公里);带距离的列表
 
业务场景
 
用户到商家距离、两点车程参考、设备间距离、按距离排序。
 
使用注意事项
 
  • 必须转为 geography 类型,否则计算的是平面距离(单位度),与真实球面距离偏差极大;
  • 结果单位为米,需除以 1000 转为公里,可通过 ROUND(结果, 1) 保留 1 位小数,提升可读性;
  • 支持点、线、面等任意空间对象的距离计算,返回的是两对象的最短距离。
 

 

2. ST_Length

 
作用:计算线对象长度
 
基础语法
 
ST_Length(线对象)
 
 
-- 示例1:计算北京到天津到上海路线的总里程
SELECT ST_Length(
  ST_MakeLine(
    ST_MakePoint(116.40, 39.90),
    ST_MakePoint(117.20, 39.13),
    ST_MakePoint(121.47, 31.23)
  )::geography
) / 1000 AS line_length_km;
-- 示例2:查询北京公交1号线的里程
SELECT ST_Length(road_geom::geography)/1000 AS bus_line_km
FROM road_info 
WHERE road_name = '北京公交1号线';
 
 
查询结果
 
线路里程数值(公里)
 
业务场景
 
GPS 轨迹总里程、道路里程、河流长度、配送路线长度。
 
使用注意事项
 
  • 仅对线对象有效,传入点 / 面对象会返回 0;
  • 转为 geography 类型后计算的是球面长度,未转换则为平面长度(单位度),无实际业务意义;
  • 可使用 ST_LengthSpheroid(线对象, 椭球体参数) 自定义椭球体,默认参数已满足绝大部分业务需求。
 

 

3. ST_Area

 
作用:计算面对象面积
 
基础语法
 
ST_Area(面对象)
 
 
示例
 
-- 示例1:计算朝阳区的面积(平方公里)
SELECT ST_Area(
  (SELECT geom FROM gsyj_gsxzbj WHERE county = '朝阳区' AND city = '北京市')::geography
) / 1000000 AS area_km2;
-- 示例2:计算洪水覆盖的面积
SELECT ST_Area(flood_geom::geography)/1000000 AS flood_area_km2
FROM flood_data 
WHERE flood_id = 'F001';
 
 
查询结果
 
面积数值(平方公里)
 
业务场景
 
行政区面积、受灾面积、农田面积、商圈覆盖面积。
 
使用注意事项
 
  • 仅对面对象有效,传入点 / 线对象会返回 0;
  • 转为 geography 类型后结果单位为平方米,需除以 1000000 转为平方公里(1 平方公里 = 1000000 平方米);
  • 若需计算亩数,可除以 666.67(1 亩≈666.67 平方米);
  • ST_Area(geom::geography, true)true 表示使用椭球体计算,精度更高,默认即为 true。
 

 

4. ST_Distance_Sphere

 
作用:快速计算两点距离(性能优先)
 
基础语法
 
ST_Distance_Sphere(点对象A, 点对象B)
 
 
示例
 
-- 示例1:快速计算用户到商家的距离
SELECT shop_name, ROUND(ST_Distance_Sphere(
  ST_MakePoint(116.38, 39.92),
  shop_geom
)/1000,1) AS distance_km
FROM shop_info;
-- 示例2:批量计算设备到基站的距离(高性能)
SELECT device_id, ROUND(ST_Distance_Sphere(device_geom, base_geom)/1000,1) AS km
FROM device_info, base_station
WHERE base_station.base_id = 'B001';
 
 
查询结果
 
距离数值(公里)
 
业务场景
 
大批量商家列表、首页附近推荐、高并发简单距离展示。
 
使用注意事项
 
  • 仅支持点对象,不支持线 / 面对象;
  • 无需转为 geography 类型,直接传入点对象即可,计算速度比 ST_Distance 快 30% 以上;
  • 精度略低于 ST_Distance(误差约 0.1%-0.5%),适合对精度要求不高的高并发场景;
  • 结果单位为米,需除以 1000 转为公里。
 

 

四、几何操作(进阶必备)

 

1. ST_Buffer

 
作用:生成缓冲圈 / 缓冲带
 
基础语法
 
ST_Buffer(空间对象, 缓冲距离, 精度参数)
 
 
示例
 
-- 示例1:生成北京中心点10公里缓冲圈(供前端展示)
SELECT ST_Buffer(
  ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326)::geography,
  10000
)::geometry AS buffer_geom;
-- 示例2:生成长安街50米缓冲带
SELECT ST_Buffer(road_geom::geography, 50)::geometry AS road_buffer
FROM road_info 
WHERE road_name = '长安街';
 
 
查询结果
 
圆形 / 带状面对象
 
业务场景
 
地图画圈展示、电子围栏、道路影响范围、基站覆盖圈、禁入区扩边。
 
使用注意事项
 
  • 缓冲距离单位为米,需先完成公里→米的转换;
  • 点→圆、线→带状、面→外扩 / 内缩(距离为负数时内缩);
  • 生成的 geography 类型缓冲圈需转为 geometry(::geometry),否则前端地图无法正常渲染;
  • 精度参数 quad_segs=32 可提升缓冲圈圆润度(默认 8),如 ST_Buffer(geom, 10000, 'quad_segs=32')
 

 

2. ST_Intersection

 
作用:取两个空间对象的重叠部分
 
基础语法
 
ST_Intersection(空间对象A, 空间对象B)
 
 
示例
 
-- 示例1:计算洪水覆盖的朝阳区面积
SELECT ST_Area(
  ST_Intersection(
    (SELECT flood_geom FROM flood_data WHERE flood_id = 'F001'),
    (SELECT geom FROM gsyj_gsxzbj WHERE county = '朝阳区')
  )::geography
)/1000000 AS flood_area_km2;
-- 示例2:提取两个商圈的重叠区域
SELECT ST_AsGeoJSON(ST_Intersection(
  (SELECT geom FROM business_circle WHERE name = '王府井'),
  (SELECT geom FROM business_circle WHERE name = '西单')
)) AS overlap_geom;
 
 
查询结果
 
重叠区域的面对象;重叠区域的面积 / GeoJSON
 
业务场景
 
洪水受灾区域、多区交叉商圈、规划重叠范围。
 
使用注意事项
 
  • 两个对象无重叠时返回 NULL,需配合 COALESCE 处理(如 COALESCE(ST_Area(...), 0),无重叠时返回 0);
  • 可通过 ST_AsText/ST_AsGeoJSON 输出重叠区域的文本 / JSON 格式,便于前端展示;
  • 支持点、线、面任意组合,返回的是重叠部分的几何对象(如点与面相交返回点,线与面相交返回线)。
 

 

3. ST_Union

 
作用:合并多个空间对象为一个
 
基础语法
 
-- 合并表中所有对象
ST_Union(空间对象)
-- 合并指定多个对象
ST_Union(对象A, 对象B)
 
 
示例
 
-- 示例1:合并北京市所有区县为一个整体面
SELECT ST_Union(geom) AS beijing_geom
FROM gsyj_gsxzbj 
WHERE city = '北京市' AND county <> '';
-- 示例2:合并用户的多个农田地块并计算总面积
SELECT ST_Union(farm_geom) AS total_farm_geom,
       ST_Area(ST_Union(farm_geom)::geography)/1000000 AS total_area_km2
FROM farm_info 
WHERE user_id = '1001';
 
 
查询结果
 
合并后的大面对象;合并对象 + 总面积
 
业务场景
 
多区县合并为市、零散地块合并、多区域统一统计。
 
使用注意事项
 
  • 按分组合并时需配合 GROUP BY(如 SELECT city, ST_Union(geom) FROM 表 GROUP BY city);
  • 合并时会自动去重、融合重叠边界,无需手动处理重复区域;
  • 大数据量合并前需创建空间索引,提升合并速度;
  • 支持点、线、面合并,点合并返回多点对象,线合并返回多线对象,面合并返回多面 / 单面对象。
 

 

4. ST_Centroid

 
作用:计算面 / 线对象的中心点
 
基础语法
 
ST_Centroid(空间对象)
 
 
示例
 
-- 示例1:计算朝阳区的中心点经纬度
SELECT 
  ST_X(ST_Centroid(geom)) AS lon,
  ST_Y(ST_Centroid(geom)) AS lat
FROM gsyj_gsxzbj 
WHERE county = '朝阳区' AND city = '北京市';
-- 示例2:计算公交线路的中点
SELECT ST_Centroid(road_geom) AS line_center
FROM road_info 
WHERE road_name = '北京公交1号线';
 
 
查询结果
 
中心点坐标;中心点对象
 
业务场景
 
区域名称标注、城市中心点、不规则区域中心定位。
 
使用注意事项
 
  • 面对象返回质心,线对象返回长度中点,点对象返回自身;
  • 质心可能落在面外部(如不规则凹面),需保证点在面内时,改用 ST_PointOnSurface
  • 可通过 ROUND(ST_X(...), 6) 保留 6 位小数(经纬度 6 位小数≈1 米精度)。
 

 

五、坐标系与前端输出

 

ST_Transform

 
作用:坐标系转换
 
基础语法
 
ST_Transform(空间对象, 目标坐标系编号)
 
 
示例
 
-- 示例1:4326转3857(供前端地图展示)
SELECT ST_Transform(
  ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326),
  3857
);
-- 示例2:批量转换表中geom的坐标系
UPDATE gsyj_gsxzbj 
SET geom = ST_Transform(geom, 3857) 
WHERE ST_SRID(geom) = 4326;
 
 
查询结果
 
转换后的空间对象;无返回(批量更新)
 
业务场景
 
后端计算(4326)→ 前端地图展示(3857)
 
使用注意事项
 
  • 转换前需通过 ST_SRID(geom) 确认原坐标系,避免重复转换导致精度丢失;
  • 常用转换场景:4326→3857(展示)、3857→4326(前端坐标转后端计算)、4326→4490(国内项目);
  • 转换后需验证:SELECT ST_SRID(ST_Transform(geom, 3857)) FROM 表 LIMIT 1;,确保转换成功。
 

 

ST_AsGeoJSON

 
作用:转前端地图可直接渲染的 JSON
 
基础语法
 
ST_AsGeoJSON(空间对象)
 
 
示例
 
-- 示例1:将10公里缓冲圈转为GeoJSON
SELECT ST_AsGeoJSON(
  ST_Buffer(ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326)::geography, 10000)::geometry
) AS buffer_geojson;
-- 示例2:批量导出区域的GeoJSON供前端渲染
SELECT area_name, ST_AsGeoJSON(geom) AS area_geojson
FROM gsyj_gsxzbj 
WHERE city = '北京市';
 
 
查询结果
 
标准 GeoJSON 字符串
 
业务场景
 
高德 / 百度 / Leaflet 地图渲染区域、路线、点位。
 
使用注意事项
 
  • 需将 geography 类型转为 geometry 后再转换,否则可能出现格式兼容问题;
  • 可通过 ST_AsGeoJSON(geom, 6) 指定坐标小数位数(6 位),减少数据体积;
  • GeoJSON 是前端 GIS 框架通用格式,无需二次解析可直接渲染。
 

 

六、高频实战扩展(必学)

 

ST_PointOnSurface

 
作用:获取面内部一定存在的点
 
基础语法
 
ST_PointOnSurface(面对象)
 
 
示例
 
-- 示例:获取朝阳区内部的点(用于地图标注)
SELECT ST_AsText(ST_PointOnSurface(geom)) AS inner_point
FROM gsyj_gsxzbj 
WHERE county = '朝阳区' AND city = '北京市';
 
 
查询结果
 
面内的点对象
 
业务场景
 
行政区划标注、区域文本展示,不会飘到区域外。
 
使用注意事项
 
  • 仅对面对象有效,线 / 点对象返回自身;
  • 保证返回的点一定在面内部,解决 ST_Centroid 质心可能在面外的问题;
  • 可配合 ST_X/ST_Y 提取坐标,用于地图标注的位置定位。
 

 

ST_Simplify

 
作用:简化几何,减少坐标点
 
基础语法
 
ST_Simplify(空间对象, 容差)
 
 
示例
 
-- 示例:简化朝阳区geom,提升前端渲染速度
SELECT ST_Simplify(geom, 0.001) AS simplified_geom
FROM gsyj_gsxzbj 
WHERE county = '朝阳区';
 
 
查询结果
 
简化后的空间对象
 
业务场景
 
前端地图加速、大数据量传输优化。
 
使用注意事项
 
  • 容差单位为度(4326 坐标系),0.001 度≈111 米,容差越大简化越彻底;
  • 简化仅减少坐标点数量,不改变对象整体形状,适合前端低精度展示;
  • 简化后的数据不可用于高精度计算,仅用于可视化。
 

 

ST_Within

 
作用:判断点是否在面内(参数更直观)
 
基础语法
 
ST_Within(被包含方对象B, 包含方对象A)
 
 
示例
 
-- 示例1:判断用户定位是否在北京市内
SELECT ST_Within(
  ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326),
  (SELECT geom FROM gsyj_gsxzbj WHERE city = '北京市' AND county = '')
);
-- 示例2:查询在电子围栏内的设备
SELECT device_id
FROM device_info
WHERE ST_Within(device_geom, (SELECT fence_geom FROM fence_info WHERE fence_id = 'F001'));
 
 
查询结果
 
true /false;符合条件的设备列表
 
业务场景
 
电子围栏、用户归属地、入区告警。
 
使用注意事项
 
  • 参数顺序为 “被包含方在前,包含方在后”,与 ST_Contains 相反,更符合日常逻辑;
  • 点在边界上时返回 false,需包含边界时改用 ST_CoveredBy(B,A)
  • 大数据量查询时,需给包含方对象创建空间索引,提升查询效率。
 

 

七、企业级万能模板(直接复制)

 
-- 模板:范围查询+距离排序+分页
SELECT
  id,
  name,
  ROUND(ST_Distance(geom::geography, ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326)::geography)/1000, 1) AS distance_km
FROM gsyj_gsxzbj
WHERE
  geom IS NOT NULL
  AND ST_DWithin(
    geom::geography,
    ST_SetSRID(ST_MakePoint(116.40, 39.90), 4326)::geography,
    10000
  )
ORDER BY distance_km ASC
LIMIT 10 OFFSET 0;
 
 

 

八、新手必避 4 大错误

 
  1. 不加 ::geography → 距离计算单位为 “度”,结果完全错误;
  2. 不建 GIST 索引 → 百万级数据查询从秒级变为分钟级,无法满足业务性能要求;
  3. 经纬度写反 → 坐标定位到海外,所有空间计算结果无意义;
  4. 坐标系不统一 → 出现对象偏移、相交误判、距离算不准等问题。
 

总结

 
  1. 所有空间计算的核心前提是绑定 4326 坐标系 + 转 geography 类型,这是避免结果错误的关键;
  2. 高频核心函数需牢记基础语法 + 使用注意事项:ST_DWithin(范围筛选)、ST_Distance(距离计算)、ST_Buffer(范围生成)、ST_AsGeoJSON(前端输出)、ST_Contains(判包含)
  3. 性能优化关键:给 geom 字段创建 GIST 空间索引,大数据量场景优先用ST_Distance_Sphere提升查询速度,前端展示前用ST_Simplify简化几何对象。
  4. 结果类型区分:
    • 布尔型:ST_Intersects/ST_Contains/ST_Covers
    • 数值型:ST_Distance/ST_Length/ST_Area
    • 空间对象型:ST_MakePoint/ST_Buffer/ST_Union/ST_Centroid
    • 列表型:范围筛选类函数(ST_DWithin/ST_Intersects)。
     
  5. 单位转换:geography 类型用米,转公里除以 1000,转平方公里除以 1000000。
posted on 2026-02-25 17:18  SheepDog1998  阅读(6)  评论(0)    收藏  举报