如何在MySQL中以公里搜索附近的位置

Posted

技术标签:

【中文标题】如何在MySQL中以公里搜索附近的位置【英文标题】:How to search nearby location with kilometer in MySQL 【发布时间】:2017-08-12 13:45:50 【问题描述】:

我有如下结构的数据库。以及如何在 5 公里内的列表中获取 location_id。数据库表中已经有经纬度数。请看我的数据库结构图。

- school_id
- location_id
- school_name
- lat
- lng

这是数据库结构图:

我已经从这个链接搜索过 How to find nearest location using latitude and longitude from sql database? 而且我看不懂代码。

SELECT id, ( 3959 * acos( cos( 弧度(37) ) * cos( 弧度( lat ) ) * cos(弧度(lng)-弧度(-122))+ sin(弧度(37))* sin( 弧度( lat ) ) ) ) 作为距离标记的距离

【问题讨论】:

见developers.google.com/maps/articles/… 是的。我已经看过那个帖子了。但我不明白什么是弧度,我怎样才能得到那个弧度。请解释一下代码。 【参考方案1】:

常量字面量3959 表示地球半径的近似值,以英里为单位。这就是“大圆距离”表达式返回以英里为单位的值的原因。

要以公里为单位,只需将 3959 替换为 6371,即地球半径的近似值,以公里为单位。

参考:https://en.wikipedia.org/wiki/Great-circle_distance


查询所做的是计算地球上两点之间的距离(以英里为单位),用纬度和经度表示。

一个点由 GCD 表达式 (37.000000,-122.000000) 中的文字值表示。另一点是数据库中行的(lat,lng)(纬度和经度)。

查询遍历表中的每一行,并计算 GCD 表达式以计算距离。 (两点之间沿球面的最短线的长度。)

HAVING distance < 25 子句排除计算距离大于或等于 25 或 NULL 的任何行。

ORDER BY distance 子句按距离值升序返回行,最近的点在前。

LIMIT 20 子句限制返回前二十行。


跟进

距离什么不到五公里?圣莫尼卡码头水族馆?

那是纬度 34.010396,经度 -118.496029。

我们可以设置用户定义的变量(以避免在我们的查询文本中传播文字):

 SET @lat =   34.010396 ;
 SET @lng = -118.496029 ;

我们的 SQL 文本在 SELECT 列表中包含我们想要从表中返回的列。我们还将包含一个看起来很复杂的“大圆距离”表达式,它返回以公里为单位的距离。

类似这样的:

 SELECT m.school_id
      , m.location_id
      , m.school_name
      , m.lat
      , m.lng

      , ( ACOS( COS( RADIANS( @lat  ) ) 
              * COS( RADIANS( m.lat ) )
              * COS( RADIANS( m.lng ) - RADIANS( @lng ) )
              + SIN( RADIANS( @lat  ) )
              * SIN( RADIANS( m.lat ) )
          )
        * 6371
        ) AS distance_in_km

  FROM mytable m
 ORDER BY distance_in_km ASC
 LIMIT 100

表达式中的 GCD 公式是计算两个点之间的距离。

在此查询中,其中一个点是常量 (@lat,@lng),我们之前将其设置为圣莫尼卡码头水族馆的坐标。

另一点是(m.lat,m.lng),即表中行的经纬度。

所以在这个查询中,distance_in_km 表示表中行的(lat,lng) 与圣莫尼卡码头水族馆之间的距离。

因为distance_in_km 值在访问行时可用,所以我们不能在WHERE 子句中引用它。

但我们可以在HAVING 子句中引用它。这与WHERE 相似,因为它过滤掉了行,但有很大不同,因为它在查询执行的后期进行评估。它可以引用在访问行时不可用的表达式,当评估 WHERE 子句时。

我们可以修改查询以包含 HAVING 子句。在这种情况下,我们限制在 100 公里以内的行,我们将只返回最近的 12 行...

  FROM mytable m
HAVING distance_in_km <= 100
 ORDER BY distance_in_km ASC
 LIMIT 12

如果我们想找到到圣莫尼卡码头以外某个点的距离,我们为该点设置@lat@lng,然后重新执行SQL。

【讨论】:

我是同样的问题,并将其用于我拥有的 gis 位置,这可以正常工作,感谢@spencer7593 即使有活动记录也能完美地为我工作。谢谢【参考方案2】:
SELECT *, ((ACOS(SIN(inputLat * PI() / 180) * 
SIN(tableColLat * PI() / 180) + COS(inputLat * PI() / 180) * 
COS(tableColLat * PI() / 180) * COS((inputLng - tableColLng) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) 
as distance FROM gm_shop HAVING distance <= 5 ORDER BY distance ASC;

距离是可以改变的。这是公里

【讨论】:

【参考方案3】:

当我解决了类似的问题而不是担心地球的曲率和角度时。我只是使用了毕达哥拉斯距离。这是一个足够接近恕我直言的近似值。

即获取所有在毕达哥拉斯距离约 5 公里的学校。

select sqrt(pow(lat - curlat,2) + pow(lng - curlng,2)) as distance from markers having distance < XXXXX

您必须计算 XXXX 的近似值。 I度约为111km。如果你没有做任何极端纬度,你不应该担心调整它。所以你可以将 XXXX 设置为 0.045

【讨论】:

因为经线远离赤道会聚,如果使用这种技术,毕达哥拉斯距离会引入太多点。

以上是关于如何在MySQL中以公里搜索附近的位置的主要内容,如果未能解决你的问题,请参考以下文章

小程序里附近的人功能实现,云开发数据库实现附近的人,按照位置远近排序,附近多少公里内的好友

百度地图圈出直径2公里

使用经纬度IOS搜索附近的人

如何使用LatLng在谷歌地图v2中以公里为单位获取两个地方之间的距离

地理位置代码获取附近的城市

百度地图里如何做一个地点2公里的范围圈。