php - mysql查询中的距离计算

标签 php mysql distance

我必须查询包含数千个条目的数据库,并根据距指定点的距离对其进行排序。

问题是每个条目都有纬度和经度,我需要检索每个条目来计算它的距离。对于大型数据库,我不想检索每一行,这可能需要一些时间。

有什么方法可以将其构建到 mysql 查询中,以便我只需要检索最近的 15 个条目。

例如

`SELECT events.id, caclDistance($latlng, events.location) AS distance FROM events ORDER BY distance LIMIT 0,15`

    function caclDistance($old, $new){
       //Calculates the distance between $old and $new
    }

最佳答案

选项 1: 通过切换到支持 GeoIP 的数据库在数据库上进行计算。

选项 2: 使用这样的存储过程对数据库进行计算:

CREATE FUNCTION calcDistance (latA double, lonA double, latB double, LonB double)
    RETURNS double DETERMINISTIC
BEGIN
    SET @RlatA = radians(latA);
    SET @RlonA = radians(lonA);
    SET @RlatB = radians(latB);
    SET @RlonB = radians(LonB);
    SET @deltaLat = @RlatA - @RlatB;
    SET @deltaLon = @RlonA - @RlonB;
    SET @d = SIN(@deltaLat/2) * SIN(@deltaLat/2) +
    COS(@RlatA) * COS(@RlatB) * SIN(@deltaLon/2)*SIN(@deltaLon/2);
    RETURN 2 * ASIN(SQRT(@d)) * 6371.01;
END//

如果您的数据库中有经纬度索引,您可以通过在 PHP 中计算初始边界框($minLat、$maxLat、$minLong 和 $maxLong)来减少需要计算的次数,并基于此将行限制为条目的子集(WHERE latitude BETWEEN $minLat AND $maxLat AND longitude BETWEEN $minLong AND $maxLong)。然后MySQL只需要对该行的子集执行距离计算。

如果您只是简单地使用存储过程来计算距离)那么 SQL 仍然必须查看数据库中的每条记录,并计算数据库中每条记录的距离,然后才能决定是否返回该行或丢弃它。

因为计算执行起来比较慢,如果你能减少需要计算的行集,消除明显落在所需距离之外的行,那会更好,这样我们就只执行较少行数的昂贵计算。

如果你认为你所做的基本上是在 map 上画一个圆,以你的初始点为中心,以距离为半径;然后公式简单地识别出哪些行落在该圆圈内......但它仍然必须检查每一行。

使用边界框就像先在 map 上绘制一个正方形,其左、右、上、下边缘与中心点的距离适当。然后我们的圆将在该框内绘制,圆上的最北端、最东端、最南端和最西端接触框的边界。有些行会落在该框之外,因此 SQL 甚至不会费心尝试计算这些行的距离。它只计算落在边界框内的那些行的距离,以查看它们是否也落在圆圈内。

在您的 PHP 中(猜测您正在从 $ 变量名运行 PHP),我们可以使用一个非常简单的计算,根据我们的距离计算出最小和最大纬度和经度,然后在 WHERE 子句中设置这些值你的 SQL 语句。这实际上是我们的盒子,落在盒子外面的任何东西都会自动丢弃,无需实际计算其距离。

Movable Type website 上对此有很好的解释(使用 PHP 代码)对于计划使用 PHP 进行任何地理定位工作的任何人来说,这应该是必不可少的阅读 Material 。

编辑 calcDistance 存储过程中的值 6371.01 是为您提供以公里为单位的返回结果的乘数。如果您想以英里、海里、米等为单位计算结果,请使用适当的替代乘数

关于php - mysql查询中的距离计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3986556/

相关文章:

php - 查询返回先前函数的内容

php - 由于当前分支的更改,Composer 不会更新

php - 如何从此 JSON 数组获取变量值?

Julia:跨观测张量广播成对距离计算

php - Laravel 5.2 关系 hasMany 与另一个唯一标识符

mysql - 如何删除MySQL中两个不同表中的重复字段

python - 现在如何在Python 2.7中使用日期时间从MYSQLdb查询数据?

php - 如何在 PHP 中循环 JSON 嵌套数组值?数据表

javascript - 谷歌地图 - computeDistanceBetween 不工作

Android:如何在连续移动时找到使用 GPS 覆盖的总距离?