我有一个MySQL表,其中包含用户名,用户的纬度和经度。

我想获取一个在给定纬度和经度,给定距离的圆或正方形内的用户列表。例如,我的输入Lat = 78.3232和Long = 65.3234且距离= 30英里。我想获取距离点78.3232和65.3234在30英里以内的用户列表。

是否可以通过单个查询解决此问题?还是可以给我提示开始解决此查询?

评论

为什么不使用PostGIS?如果您正在启动地理项目,则仍然可以更改堆栈

stackoverflow.com/a/40272394/1281385在加快此查询速度(如果需要)中应该很有用

我认为他的计算方法不正确。我正在尝试计算布尔加斯(BOJ-42.416668,27.283333)和瓦尔纳(VAR-43.237260,27.829096)之间的距离。与此请求(6371 * acos(cos(弧度(43.237260))* cos(弧度(lat))* cos(弧度(lon)-弧度(27.829096))+ sin(弧度(43.237260))* sin(弧度(lat ))))AS距离的结果是101,52135729600961 KM,在Google地图中,距离是78.88 km。 ![在此处输入图片描述](i.stack.imgur.com/FGnCC.png)

#1 楼

该SQL语句将查找距78.3232、65.3234坐标30英里范围内最近的20个位置。它根据该行的纬度/经度和目标纬度/经度计算距离,然后仅询问距离值小于30英里的行,按距离对整个查询进行排序,并将其限制为20个结果。要按公里而不是英里进行搜索,请将3959替换为6371。

SELECT
  id, (
    3959 * acos (
      cos ( radians(78.3232) )
      * cos( radians( lat ) )
      * cos( radians( lng ) - radians(65.3234) )
      + sin ( radians(78.3232) )
      * sin( radians( lat ) )
    )
  ) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;


这是将Google Maps API v3与您已经拥有的MySQL后端一起使用。 >
https://developers.google.com/maps/articles/phpsqlsearch_v3#findnearsql

评论


使用此选项时,我在选择中遇到语法错误,“#1582-对本机函数'radians'的调用中不正确的参数计数可能是什么?

– bluantinoo
2014年11月29日在2:09

发现:我的lng变量为空!抱歉!

– bluantinoo
2014年11月29日10:38

正是我想要的,但是数千条记录的查询性能超载了什么?准确性如何?

–阿米莎(Amit Shah)
19年2月5日,12:01

更好地将其替换为6371392.896以进行米数搜索

–Vasilii Suricov
19年2月6日在22:32

是否无法像我这样将距离结果从2.71250308462937983478013848070986568927764892578125减少到2.71?

–阿里·阿迪尔(Ali Adil)
20-2-28在19:45

#2 楼

Mapperz的答案无效。窦必须根据纬度而不是经度来计算。
因此,corect SQL语句为:

SELECT
    id, (
      3959 * acos (
      cos ( radians(78.3232) )
      * cos( radians( lat ) )
      * cos( radians( lng ) - radians(65.3234) )
      + sin ( radians(78.3232) )
      * sin( radians( lat ) )
    )
) AS distance
FROM markers
HAVING distance < 30
ORDER BY distance
LIMIT 0 , 20;


评论


您的答案应排在第一位。

–阿米莎(Amit Shah)
19年2月5日在12:06

@AmitShah如果您认为可以对提问者(@shihabK在站点上活跃了将近6年)进行ping操作和/或投票给meta.stackexchange.com/questions/268666/…

– PolyGeo♦
19年2月6日在23:33



这应该是公认的答案。

–catbadger
19-09-28在13:08

#3 楼

创建函数可能是基础..因此您可以在其他区域重用它。也会使您的查询更整洁...至少那是我的2美分。

DELIMITER $$

CREATE FUNCTION calcDistance(lat FLOAT, lng FLOAT, pnt_lat FLOAT, pnt_lng FLOAT)
    RETURNS FLOAT
BEGIN

    DECLARE dist FLOAT;
    SET dist =
          3959 * acos(
                cos(radians(pnt_lat))
                * cos(radians(lat))
                * cos(radians(lng) - radians(pnt_lng))
            + sin(radians(pnt_lat))
                    * sin(radians(lat))
          );

    RETURN dist;

END


评论


如果您修复代码样式,答案将被否决。这是正确的方法

–Vasilii Suricov
19年2月6日在23:31



#4 楼

现在是2020年,您应该使用RDBS的内置空间功能。在这种情况下,您需要使用ST_Distance函数。
-- geo column in users table is of Geometry data type, with a spatial index
SET @g1 = ST_SRID(POINT(78.3232, 65.3234), 4326);
SELECT * from users WHERE ST_Distance(users.geo, @g1, 'foot') < 158400; -- 5280 feet per mile


评论


如果除此之外,我们还想按距离对它们进行排序呢?第一个,最接近的一个。我们是否使用ORDER BY ...?非常感谢@JohnC

–里卡多
20-10-24在15:53

@Ricardo正确,您可以将空间函数放在order by子句中。确保您也有一个空间索引。

– John C
20-10-28在6:11



#5 楼

这是我的查询变体,似乎稍微容易一些(http://dexxtr.com/post/83498801191/how-to-determine-point-inside-circle-using-mysql)

SELECT 
    *
FROM 
    `locator`
WHERE
    SQRT(POW(X(`center`) - 49.843317 , 2) + POW(Y(`center`) - 24.026642, 2)) * 100 < `radius`


评论


这比较容易,但忽略了地球是弯曲的这一事实。

– Tim Rijavec
2015年6月3日,13:35

需要一个公式才能准确。也许这仅在短距离上会比较好:D

– Jethro
15年12月27日在16:49

你会发射导弹,还是什么?

–丹尼斯·布拉加(Dennis Braga)
19年6月11日在14:12

@DennisBraga-如果是这样,那么也许这个问题是题外话,更适合http://globalthermonuclearwar.stackexchange.com ...?

–ashleedawg
19年8月22日在9:37