MySQL-如何获取具有多个经度和纬度的最近位置?

问题描述

我找到了一些不错的建议https://pypi.org/project/RESTinstance/,以找到一对具有单一经度和纬度的位置。但是,我正在寻找一种有效的方法来查找一组(多对)纬度和经度附近的位置。然后将结果分组。我可以在MysqL中使用UNION在下面编写的查询中使用。但是我正在寻找没有UNION的方法。我的表格(user_locations)

+----+--------+-----------+-----------+-----------------------------+
| id | userid | lat       | lng       | point                       |
+----+--------+-----------+-----------+-----------------------------+
| 1  | 18     | 48.204784 | 16.369640 | POINT(16.369640,48.204784) |
+----+--------+-----------+-----------+-----------------------------+
| 2  | 21     | 48.205872 | 16.368946 | POINT(16.368946,48.205872) |
+----+--------+-----------+-----------+-----------------------------+
| 3  | 11     | 48.205914 | 16.367867 | POINT(16.367867,48.205914) |
+----+--------+-----------+-----------+-----------------------------+

具有一个纬度和经度对的查询:查找[48.205546,16.368667]附近的用户

SELECT 
  name,( 3959 * acos( cos( radians(48.205546) ) * cos( radians( locations.lat ) ) 
   * cos( radians(locations.lng) - radians(16.368667)) + sin(radians(48.205546)) 
   * sin( radians(locations.lat)))) AS distance 
FROM user_locations 
WHERE active = 1 
HAVING distance < 10 
ORDER BY distance;

我希望将上面的查询与一组给定的经度一起使用:查找附近的用户: [[48.205546,16.368667],[48.205084、16.369712],[48.205660、16.367947]]

SELECT 
      name,( 3959 * acos( cos( radians($lat1,$lat2,$lat3,$lat4) ) * cos( radians( locations.lat ) ) 
       * cos( radians(locations.lng) - radians($lng1,$lng2,$lng3,$lng4)) + sin(radians($lat)) 
       * sin( radians(locations.lat)))) AS distance 
    FROM user_locations 
    WHERE active = 1 
    HAVING distance < 10 
    ORDER BY distance;

我并不是真正在寻找特定的输出,因为结果将被分组,所以距离并不是那么重要。用户18可能靠近多个纬度对。将结果与userid分组只会检索一行userid:18。

    +----+--------+-----------+-----------+-----------------------------+--+
| id | userid | lat       | lng       | point                       |  |
+----+--------+-----------+-----------+-----------------------------+--+
| 2  | 21     | 48.205872 | 16.368946 | POINT(16.368946,48.205872) |  |
+----+--------+-----------+-----------+-----------------------------+--+
| 3  | 11     | 48.205914 | 16.367867 | POINT(16.367867,48.205914) |  |
+----+--------+-----------+-----------+-----------------------------+--+

解决方法

收集:[[48.205546,16.368667],[48.205084,16.369712],[48.205660,16.367947]]

Hacky解决方案:

SELECT  locations.*  FROM    user_locations AS locations
WHERE   (MBRContains
                (
                LineString
                        (
                        Point (
                                16.368667 + 10 / ( 111.320 / COS(RADIANS(48.205546))),48.205546 + 10 / 111.133
                              ),Point (
                                16.368667 - 10 / ( 111.320 / COS(RADIANS(48.205546))),48.205546 - 10 / 111.133
                              ) 
                        ),locations.point
                )
                OR MBRContains
                (
                LineString
                        (
                        Point (
                                16.369712 + 10 / ( 111.320 / COS(RADIANS(48.205084))),48.205084 + 10 / 111.133
                              ),Point (
                                16.369712 - 10 / ( 111.320 / COS(RADIANS(48.205084))),48.205084 - 10 / 111.133
                              ) 
                        ),locations.point
                )
                      OR MBRContains
                (
                LineString
                        (
                        Point (
                                16.367947 + 10 / ( 111.320 / COS(RADIANS(48.205660))),48.205660 + 10 / 111.133
                              ),Point (
                                16.367947 - 10 / ( 111.320 / COS(RADIANS(48.205660))),48.205660 - 10 / 111.133
                              ) 
                        ),locations.point
                ))
                
                
                      
                
                
        

查询持续时间:0.109秒(精细)。
注意:点域具有空间索引

10(公里内的距离)

16.368667(长)

48.205546(lat)