【发布时间】:2010-07-16 13:40:12
【问题描述】:
我有一个 SQL 数据库,用于存储来自 iPhone 应用程序的经度和纬度。我需要查询从给定位置开始到另一个最远位置的所有记录。
例如,我有经度 x 和纬度 y。我首先想要所有记录,其经度与 x 最接近,纬度与 y 最接近。我需要从最近到最远的链中的所有记录。位置越远,经纬度的值就会比x和y大。
我希望你明白这一点,我正在等待答案。
【问题讨论】:
我有一个 SQL 数据库,用于存储来自 iPhone 应用程序的经度和纬度。我需要查询从给定位置开始到另一个最远位置的所有记录。
例如,我有经度 x 和纬度 y。我首先想要所有记录,其经度与 x 最接近,纬度与 y 最接近。我需要从最近到最远的链中的所有记录。位置越远,经纬度的值就会比x和y大。
我希望你明白这一点,我正在等待答案。
【问题讨论】:
距离与经纬度不是简单的计算,而是需要球面三角学的。
acos(cos(lat1)*cos(lon1)*cos(lat2)*cos(lon2) +
cos(lat1)*sin(lon1)*cos(lat2)*sin(lon2) +
sin(lat1)*sin(lat2)) * R(adius of the earth)
所以这个查询
select locID, locName, locDesc, lat, lon, locDiffMeters
from (select locID, locName, locDesc, lat, lon,
acos(cos($lat)*cos($lon)*cos(lat)*cos(lon) +
cos($lat)*sin($lon)*cos(lat)*sin(lon) +
sin($lat)*sin(lat) ) * 6,371,000 -- earths radius in meters
as locDiffMeters
from locationTable
where locID <> $ID
) a
order by locDiffMeters
可能是正确的答案,假设你有一个数学库的能力。
【讨论】:
类似于 Fosco,但使用毕达哥拉斯定理:
select locID, locName, locDesc, lat, lon, locDiff from
(select locID, locName, locDesc, lat, lon,
sqrt((lat - $LAT)*(lat - $LAT) + (lon - $LON)*(lon - $LON)) as locDiff
from locationTable
where locID <> $ID) a
order by locDiff
对于非常大的距离(或远离赤道的位置),您最好使用测地线。
【讨论】:
假设您已经查询了起始位置 lat/lon 和位置 ID...我使用 $LAT、$LON 和 $ID 作为占位符:
select locID, locName, locDesc, lat, lon, locDiff
from (
select locID, locName, locDesc, lat, lon, ABS(lat - $LAT) + ABS(lon - $LON) as locDiff
from locationTable
where locID <> $ID
) a
order by locDiff
希望这会有所帮助...可能不是最优化的方法,但应该非常接近。
【讨论】:
如果您不必处理大距离(请参阅 Adam 的回答),您可以考虑使用 PostgreSQL 的 geometric types 和关联的 functions。
【讨论】:
如果您使用的是 Postgresql,请添加 PostGIS 扩展名并查看 ST_Distance_Sphere
ST_Distance_Sphere — 返回两个 lon/lat 几何图形之间的最小距离(以米为单位)。使用球形地球,半径为 6370986 米。比 ST_Distance_Spheroid 快,但不太准确。 1.5 之前的 PostGIS 版本仅针对点实现。
SELECT round(CAST(ST_Distance_Sphere(ST_Centroid(the_geom), ST_GeomFromText('POINT(-118 38)',4326)) As numeric),2) As dist_meter ...
【讨论】: