mysql查询中的距离计算

我必须查询成千上万个条目的数据库,并按距指定点的距离对其进行排序。

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

有什么办法可以将其构建到mysql查询" title="mysql查询">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)并限制来减少需要计算的数量。根据该行($ minLat和$ maxLat之间的纬度以及$ minLong和$

maxLong之间的经度)将这些行添加到您的条目子集。然后,MySQL只需要为该行子集执行距离计算。

如果您只是使用存储过程来计算距离,则SQL仍然必须遍历数据库中的每个记录,并计算数据库中每个记录的距离,然后才能决定是返回该行还是丢弃该行。

由于计算的执行速度相对较慢,因此最好减少需要计算的行的集合,从而消除明显落在所需距离之外的行,因此我们仅对以下情况执行昂贵的计算:行数较少。

如果您认为自己所做的基本上是在地图上绘制一个以初始点为中心并具有一定距离半径的圆;那么该公式仅会确定哪些行属于该圆…但是它仍然必须检查每一行。

使用边界框就像先在地图上绘制一个正方形,然后将左,右,上和下边缘与我们的中心点保持适当的距离。然后,我们将在该框中绘制圆,使圆上的最北,最东,最南和最西点与框的边界接触。一些行将落在该框的外面,因此SQL甚至不必费心尝试计算这些行的距离。它仅计算落入边界框内的行的距离,以查看它们是否也落入圆内。

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

在Movable Type网站上对此有很好的解释(带有PHP代码),对于打算用PHP进行任何GeoPositioning工作的任何人来说,这都是必不可少的阅读材料。

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

以上是 mysql查询中的距离计算 的全部内容, 来源链接: utcz.com/qa/406186.html

回到顶部