gpt4 book ai didi

php - mysql查询中的距离计算

转载 作者:行者123 更新时间:2023-11-29 03:49:40 29 4
gpt4 key购买 nike

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

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

有什么方法可以将其构建到 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/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com