PHP/MySQL:从数据库中选择靠近给定位置的位置
-
23-08-2019 - |
题
在 PHP 中,我有以下代码用于计算两个位置之间的距离:
<?php
function distance($lat1, $long1, $lat2, $long2) {
// DEGREE TO RADIAN
$latitude1 = $lat1/180*pi();
$longitude1 = $long1/180*pi();
$latitude2 = $lat2/180*pi();
$longitude2 = $long2/180*pi();
// FORMULA: e = ARCCOS ( SIN(Latitude1) * SIN(Latitude2) + COS(Latitude1) * COS(Latitude2) * COS(Longitude2-Longitude1) ) * EARTH_RADIUS
$distance = acos(sin($latitude1)*sin($latitude2)+cos($latitude1)*cos($latitude2)*cos($longitude2-$longitude1))*6371;
return $distance;
}
echo distance(9.9921962, 53.5534074, 9.1807688, 48.7771056); // Hamburg, DE - Stuttgart, DE
?>
但现在,我想通过 PHP 从 MySQL 数据库中选择靠近给定位置的位置:
- 用户输入家乡
- 我的脚本通过 Google API 获取纬度/经度值
- 在我的数据库中,大约有 200 个位置,其中有一个纬度值字段和一个经度值字段
- 我需要 PHP 和 MySQL 的代码来选择距离用户家乡最近的 10 个位置
我希望你可以帮助我。提前致谢!
解决方案
MySQL 大圆距离(半正矢公式) 正是您所需要的。
然而,只有 200 条记录,您也可以加载所有记录并使用代码检查它们。数据集确实太小了,无法过多担心数据库与代码或任何其他此类优化。
在PHP中计算邮政编码之间的距离 有几个该算法的 PHP 实现。
地理位置邻近搜索 与您遇到的问题几乎完全相同。
其他提示
也许像
SELECT field1, field2, ...,
ACOS(SIN(latitude / 180 * PI()) * SIN(:1) + COS(latitude / 180 * PI()) * COS(:2) * COS(:2 - longtidude)) * 6371 AS distance
ORDER BY distance ASC;
或者
SELECT field1, field2, ...,
ACOS(SIN(RADIANS(latitude)) * SIN(:1) + COS(RADIANS(latitude)) * COS(:2) * COS(:2 - longtidude)) * 6371 AS distance
ORDER BY distance ASC;
(直接从PHP代码翻译而来)
:1
和 :2
是 $lat2/180*pi()
和 $long2/180*pi()
分别。
这就是半正矢公式。您可以将 PHP 直接转换为 SQL,以便可以在空间上查询数据库(另一种方法是从数据库中提取每条记录并通过 PHP 运行数据)。MySQL 提供了您需要的所有数学函数。
我为一个商业网站执行此操作,该网站提供基于邮政/邮政编码的距离查找,因此在没有特定 GIS 功能的情况下当然是可能的。
MySQL 中有一些函数可以用来完成此任务。
http://dev.mysql.com/doc/refman/5.0/en/gis-introduction.html
MySQL 能够对行进行地理空间索引。你可能不需要自己做这个数学运算(你可以让 MySQL 计算两个地理对象之间的距离并按其排序......)。
刚刚跨过这个话题。也许有人会对这个函数感兴趣,在MySql 5.7中测试过:
create function GetDistance(lat1 real, lng1 real, lat2 real, lng2 real) returns real no sql
return ATAN2(SQRT(POW(COS(RADIANS(lat2)) * SIN(RADIANS(lng1 - lng2)), 2) +
POW(COS(RADIANS(lat1)) * SIN(RADIANS(lat2)) - SIN(RADIANS(lat1)) *
COS(RADIANS(lat2)) * COS(RADIANS(lng1 - lng2)), 2)),
(SIN(RADIANS(lat1)) * SIN(RADIANS(lat2)) + COS(RADIANS(lat1)) *
COS(RADIANS(lat2)) * COS(RADIANS(lng1 - lng2)))) * 6372.795;
呼叫:
select GetDistance(your_latitude, your_longitude, table_field_lat,
table_field_lng) as dist from [your_table] limit 5;
为什么不使用 MySQL 的地理空间功能...?不仅仅在开玩笑。
如果 200 条记录是城镇等实际地点,那么您可以使用 GeoNames 的 API 作为替代方案吗?
以下网络服务将提供距离所提供的纬度和经度最近的 10 个位置:
http://ws.geonames.org/findNearby?lat=47.3&lng=9
来源: http://www.geonames.org/export/web-services.html#findNearbyPlaceName