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

MySQL - How to get nearest locations with multiple latitudes and longitudes?

我找到了一些很好的建议 here 来查找具有一对单一纬度和经度的最近位置。但是我正在寻找一种有效的方法来找到具有一组(多个)纬度和经度对的最近位置。然后对结果进行分组。我可以将 mysql 中的 UNION 与我在下面编写的查询一起使用。但是我正在寻找没有 UNION 的方法。我的 table (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]]

骇人听闻的解决方案:

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 秒(正常)。
注意:点域有SPATIAL索引

10(千米以内的距离)

16.368667(长)

48.205546(纬度)