匹配最近的经度/纬度

时间:2011-02-13 02:49:08

标签: mysql geospatial latitude-longitude

使用Maxmind的GeoIP软件,我们可以在80%的时间内将IP地址的LONG / LAT范围缩小到25英里内的相对精确度。

现在,我们不想使用MaxMind提供的任何其他信息,因为要素名称(即城市)之间存在很多差异,无法进行查找。如果其他方法无法找到某个功能,我们计划尝试进行此类查找,但出于性能原因,查看浮点数比字符串快得多。

现在,我对如何找到从Maxmind到我们的数据库的最接近的匹配LAT / LONG有点无能为力。问题是,与Maxmind相比,我们的数据库功能具有更高的精度,因此直接比较可能无效。如果我们在查询期间尝试将ROUND()应用于列,那显然会非常慢。

鉴于以下数据,最快的方式就是

LONG 79.93213 LAT 39.13111

SELECT `feature_name` FROM `geo_features`
WHERE long BETWEEN 79.93 AND 79.79.94
AND lat BETWEEN 39.13 AND 39.14

任何优雅的解决方案都能快速发展吗?我知道MySQL 5中有一些新的空间存储类型,也许任何人都可以提供一个解决方案,而不仅仅是我似乎对自己提出的障碍。

1 个答案:

答案 0 :(得分:8)

优雅(更准确)的做法(但不是快速

// Closest within radius of 25 Miles
// 37, -122 are your current coordinates
// To search by kilometers instead of miles, replace 3959 with 6371
SELECT feature_name, 
 ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) 
  * cos( radians( long ) - radians(-122) ) + sin( radians(37) ) 
  * sin( radians( lat ) ) ) ) AS distance 
FROM geo_features HAVING distance < 25 
ORDER BY distance LIMIT 1;

修改

这是Haversine formula用于计算与地理坐标的圆距离。以下是different platforms

中此公式的一些实现
R = earth’s radius (mean radius = 6,371km)
Δlat = lat2− lat1
Δlong = long2− long1
a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
c = 2.atan2(√a, √(1−a))
d = R.c
// Note that angles need to be in radians to pass to Trigonometric functions