MySQL:尝试理解SELECT查询以获取附近的位置

时间:2015-07-07 08:18:00

标签: mysql database google-maps

当我们在数据库中存储纬度和经度时,经历了许多关于如何找到附近位置的SO问题,我多次遇到Alexander Rubin(他是MySQL AB高级顾问)的this演示文稿/ p>

CREATE PROCEDURE geodist (IN userid int, IN dist int)
BEGIN
    declare mylon double; declare mylat double;
    declare lon1 float; declare lon2 float;
    declare lat1 float; declare lat2 float;

-- get the original lon and lat for the userid
    select longitude, latitude into mylon, mylat from users where id=userid limit 1;

-- calculate lon and lat for the rectangle:
    set lon1 = mylon-dist/abs(cos(radians(mylat))*69);
    set lon2 = mylon+dist/abs(cos(radians(mylat))*69);
    set lat1 = mylat-(dist/69); 
    set lat2 = mylat+(dist/69);

-- run the query:
    SELECT destination.*, 3956 * 2 * ASIN(SQRT(POWER(SIN((orig.lat - dest.lat) * pi()/180 / 2), 2) + COS(orig.lat * pi()/180) * COS(dest.lat * pi()/180) * POWER(SIN((orig.lon - dest.lon) * pi()/180 / 2), 2) )) as distance FROM users destination, users origin WHERE origin.id=userid and destination.longitude between lon1 and lon2 and destination.latitude between lat1 and lat2 having distance < dist ORDER BY Distance limit 10;
END $$

如果我理解正确,这里涉及两个表。 destinationlongitudelatitudeusers也有longitudelatitudeid列。该过程将用户ID和距离作为输入参数,并从users中找出用户的位置,然后找到用户附近的destination中的行。

现在,我对MySQL相对较新,因此发现很难理解该过程,特别是他提到的最后一次SELECT查询。请有人解释一下我的疑惑:

  1. 什么是orig.lat,dest.lat,orig.lon,dest.lon&amp; origin.id?在此程序之前,我无法找到它的参考资料。

  2. FROM users destination, users origin是什么意思?如果我们查询两个表,我们的名字之间不能有逗号吗?此外,之前没有提及实体origin

3 个答案:

答案 0 :(得分:1)

如果您想从数据库中找到附近的位置,请使用 Geohash

例如,您可以通过Geohash将57.64911,10.40744编码为u4pruydqqvj,然后将其放入数据库中。

如果您想在19米范围内找到位置。您可以在MySQL中使用WHERE geohash LIKE 'u4pruydq%'

如果您想在2.4公里范围内找到位置,请使用WHERE geohash LIKE 'u4pruy%'

计算MySQL中的每个距离都是效率太低。

答案 1 :(得分:1)

让我们讨论你问题的第二部分:

在上一个Select Query中,只涉及一个表'users'。它被使用了两次。 'destination'和'origin'用作此表的别名。这样,您可以使用不同的别名将每一行与同一表中的其他行进行比较。我也不确定,但它是自我加入的另一种选择。

编写该过程是为了查找某个距离范围内的所有用户(通过使用经度和纬度值创建矩形来定义)。

在第一个选择查询中,他只选择了users表中的“ONE”记录,该记录成为原始记录或基本记录。作者使用同一表的两个别名,即'origin'成为基本用户记录,'destination'用于找出位于邻域中矩形区域内的所有用户。这就是作者使用'Select destination。*'的原因,它将列出满足Where子句标准(距离范围)的用户表的所有记录。

数学公式只计算附近用户与原点的距离。 where子句匹配userid(过程的输入)和origin.id作为我们的基本记录,每条记录都应与此记录进行比较。

我认为'dest'和'orig'应该是'destination'和'origin',因为使用相同的别名更有意义,我认为这可能是一个错误。

我希望在这个阶段你会明白'origin.id'是什么意思。这很简单; origin是users表的别名,因此'id'实际上是一个users表列。

我希望我的解释对你有帮助!

答案 2 :(得分:0)

它只使用一个表格users,其中包含两个别名:origindestination

Origin用于查找给定用户的位置,目的地用于查找给定距离内的其他用户。

由于性能原因,where子句使用between来查找半径为dist的圆的最小边界矩形内的用户,然后使用{{1}将其另外过滤到所需的圆圈}}

此外,第一个查询似乎有点多余,整个过程可以通过单个查询来完成。