MySQL选择范围内的坐标
Posted
技术标签:
【中文标题】MySQL选择范围内的坐标【英文标题】:MySQL select coordinates within range 【发布时间】:2014-01-29 07:32:20 【问题描述】:我的数据库中有 100 000 个地址(即记录)。
每一个都有自己的坐标(纬度和经度)。
现在,鉴于用户的地理位置(纬度和经度),我想在地图上仅显示 5 英里范围内的地址(使用 Google maps v3 API)。
这意味着通常只需显示 100 000 个地址中的 5 或 6 个地址。
一种解决方案可能是检索所有记录并在 Java 中应用一个公式来计算每个地址的距离,并且仅当它在范围内时才显示它。
这会浪费处理能力,因为我需要检索所有记录,而我只需要在地图上显示 5 或 6 条记录。
如何在数据库端(mysql)解决这个问题,以便只返回 5 英里范围内的地址?
【问题讨论】:
Haversine calculation: Show users within set 的可能重复项 7 年后接受答案怎么样? 【参考方案1】:我认为 MySQL 的地理空间扩展可以为您解决这个问题:https://dev.mysql.com/doc/refman/8.0/en/spatial-convenience-functions.html#function_st-distance-sphere
否则,您可以在纬度上编制索引,然后查询 WHERE lattitude > userLat-5miles 和 lattitude
【讨论】:
【参考方案2】:DELIMITER $
DROP FUNCTION IF EXISTS calc_distance$
CREATE FUNCTION calc_distance(
user_lat FLOAT(9,6),
user_lng FLOAT(9,6),
field_lat FLOAT(9,6),
field_lng FLOAT(9,6)
) RETURNS INTEGER
BEGIN
DECLARE ulat FLOAT;
DECLARE ulng FLOAT;
DECLARE flat FLOAT;
DECLARE flng FLOAT;
SET ulat = RADIANS(user_lat);
SET ulng = RADIANS(user_lng);
SET flat = RADIANS(field_lat);
SET flng = RADIANS(field_lng);
RETURN
6371393
* ACOS(
COS(ulat) * COS(flat) * COS(flng - ulng)
+ SIN(ulat) * SIN(flat)
);
END$
DELIMITER ;
用法
if (($radius = $search->getRadiusMeters()))
$query['where'][] = "calc_distance($lat, $lng, addr.lat, addr.lng) < $radius";
【讨论】:
它将提高执行时间【参考方案3】:我的方法 - 我正在使用它 - 像技术人员一样思考,我对 +/- 5% 感到满意
此解决方案并非用于控制火箭、船只等,仅适用于~100km 以下的距离它只是一个类似Fermi problem的解决方案
让我们开始一个务实的解决方案:
第一:对于很多问题我们可以忽略地球不是平的(距离
地球的周长或多或少是 40000 公里(由于某种原因或多或少)
一个圆正好有 360 度。
所以 1 公里是:360/40000 度 => 0.00278 度
然后只需在每公里 0.003 范围内选择纬度/经度,这将类似于 long > 42 - 0.003 和 long
问题:结果是正方形而不是圆形(不是实际距离)
如果需要圈子,在得到结果后编写脚本。
我只是展示了官方的厕所,距离为 2 公里,所以正方形是可以的,准确度也可以。原因是,有街道有房子,人不能直接走路……
编辑:技术/数学解释:
对于非常小的三角形(一个角度
【讨论】:
【参考方案4】:您可以使用所谓的Haversine formula。
$sql = "SELECT *, ( 3959 * acos( cos( radians(" . $lat . ") ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(" . $lng . ") ) + sin( radians(" . $lat . ") ) * sin( radians( lat ) ) ) ) AS distance FROM your_table HAVING distance < 5";
$lat
和 $lng
是您点的坐标,而 lat/lng 是您的表格列。以上将列出 5 nm 范围内的位置。将3959
替换为6371
以更改为公里。
此链接可能有用:https://developers.google.com/maps/articles/phpsqlsearch_v3
编辑:我没有看到你提到 Java。这个例子是用 PHP 编写的,但查询仍然是您所需要的。
【讨论】:
以上是关于MySQL选择范围内的坐标的主要内容,如果未能解决你的问题,请参考以下文章