前言
查询附近500米数据,第一反应是用ST_Buffer,但是ST_Buffer文档写了一句话,使用ST_DWithin效率更高。
ST_Buffer (postgis.net)
ST_DWithin (postgis.net)
数据取点
我有一种坐标系4326的表ne_10m_admin_0_boundary_lines_land,取gid=1的这条数据,geom是个线串,我们取第一个点-124.75886592699995 48.49401784300004
我们把x坐标-1度,只在这个点附近-125.75886592699995 48.49401784300004
知识科普
3857坐标系单位是米。也叫投影、平面、墨卡托
4326坐标系单位是度。也叫WGS 84,球面坐标,大地2000是4490,相同原理
在地球表面,线性距离的计算会受到地球的曲率影响。在赤道附近,一度的经度对应的线性距离大致为111千米。然而,随着你向极地区域移动,每度经度的线性距离会减小。在极地附近,经度线会收缩成一个点,所以在极地附近的地理坐标系下,1度经度的线性距离会变得非常小。
如图所示,坐标系不同,所以单位也不同
查询方案1
方案1用的ST_DWithin第1个构造
boolean ST_DWithin(
geometry , geometry , double precision g1g2distance_of_srid)
对于几何图形:距离以几何图形的空间参考系统定义的单位指定。 为了使此函数有意义,源几何图形必须位于同一坐标系中(具有相同的 SRID)。需要把坐标系转成3857。如果用4326,他会按照度去计算。
比如-125,使用4326,最后1个参数是1,那么他会按照-125+1去处理。
如果使用3857,他会按照1度约等于110KM去处理。
--查询附近1000*120米附近的数据
SELECT gid,geom
FROM ne_10m_admin_0_boundary_lines_land nmlolp
WHERE ST_DWithin(ST_Transform(geom,3857), ST_Transform('SRID=4326;POINT(-125.75886592699995 48.49401784300004)',3857), 1000 * 120)
ORDER by gid
limit 10
因为这张表是4326坐标系,由于插入的是几何数据,所以需要坐标系的转换。
如果使用距离<1000 * 120,是查不到这条数据。从而也验证了度和米的转换。
查询方案2
方案2用的ST_DWithin第2个构造
boolean ST_DWithin(
geography , geography , double precision , boolean gg1gg2distance_metersuse_spheroid = true)
;
对于地理:距离测量默认为,单位为米。 为了更快地进行评估,请使用在球体上进行测量。
--查询附近500米附近的数据
select gid,geom
from ne_10m_admin_0_boundary_lines_land nmlolp
where ST_DWithin(geom::geography,'POINT(-125.75886592699995 48.49401784300004)'::geography,500)
用地理构造的好处是,不需要进行坐标系转换,虽然强转地理类型之后是4326,但是不影响后面米的计算。