我有一张包含咖啡馆的lat / lon的桌子。我想做一个SQL查询,它给了我最近的咖啡馆到每个咖啡馆。有人可以提供有关如何执行此操作的建议吗?
表格基本上如下:
Cafe ID
+-------------------------+----------------------+----------------------+
| cafe_id | gps_latitude | gps_longitude |
+-------------------------+----------------------+----------------------+
| 011-1003 | 55.86649500000000000 | 8.16856200000000000 |
| 192-143 | 57.04419159749860000 | 10.36447024359820000 |
| 037-0233 | 55.08773849210000000 | 8.56101036070000000 |
| 121-934 | 56.89120900000000000 | 9.16818100000000000 |
+-------------------------+----------------------+----------------------+
非常感谢任何帮助!
答案 0 :(得分:2)
答案 1 :(得分:2)
您可以使用Spherical Law of Cosines获取earth-radii中表达的距离。
有些人更喜欢Haversine formula,因为它提供了更好的精度,但鉴于MySql的浮点精度足够高,两者之间的差异可以忽略不计。第一个更容易实现:
select c1.cafe_id,
substring_index (
group_concat( C2.cafe_id order by
acos( sin(radians(c1.gps_latitude)) * sin(radians(c2.gps_latitude))
+ cos(radians(c1.gps_latitude)) * cos(radians(c2.gps_latitude))
* cos(radians(c2.gps_longitude-c1.gps_longitude)) ) ),
',', 1) nearest
from cafe c1
inner join cafe c2 on c1.cafe_id <> c2.cafe_id
group by c1.cafe_id
样本数据的输出是:
| cafe_id | nearest |
|----------|----------|
| 011-1003 | 037-0233 |
| 037-0233 | 011-1003 |
| 121-934 | 192-143 |
| 192-143 | 121-934 |
这是MySql fiddle。
距离计算在order by
聚合函数的group_concat
子句中使用,该子句以逗号分隔的 cafe_id 值列表按照其距离的顺序排列你分组的咖啡馆。 substring_index
函数从该列表中提取第一个项目。
连接条件很重要,因为没有它你会把咖啡馆本身当作最近的邻居(它的距离显然是0)。
在评论中,您要求仅包含某个半径范围内的邻居。
在这种情况下,您可以输出“距离”,转换为km(英里将是一个不同的因素):
select c1.cafe_id,
substring_index (
group_concat( C2.cafe_id order by
acos( sin(radians(c1.gps_latitude)) * sin(radians(c2.gps_latitude))
+ cos(radians(c1.gps_latitude)) * cos(radians(c2.gps_latitude))
* cos(radians(c2.gps_longitude-c1.gps_longitude)) ) ),
',', 1) nearest,
min (
acos( sin(radians(c1.gps_latitude)) * sin(radians(c2.gps_latitude))
+ cos(radians(c1.gps_latitude)) * cos(radians(c2.gps_latitude))
* cos(radians(c2.gps_longitude-c1.gps_longitude)) ) )
* 6371 km
from cafe c1
inner join cafe c2 on c1.cafe_id <> c2.cafe_id
group by c1.cafe_id
现在您可以根据距离决定是否要忽略邻居。如果您真的想要排除最近邻居太远的咖啡馆,那么最后添加一个having
条款:
having km < 5
如果你喜欢里程,那么在SQL中使用3959作为乘法因子而不是6371。
答案 2 :(得分:1)
Bellow查询有助于找出两个(邻居)最近的位置。
使用当前的lat和lng值在MySQL中设置变量
(SELECT tbl.cafe_id , tbl.gps_latitude, tbl.gps_longitude, 111.045 * DEGREES(ACOS(COS(RADIANS(@lat))
* COS(RADIANS(gps_latitude))
* COS(RADIANS(gps_longitude) - RADIANS(@lng))
+ SIN(RADIANS(@lat))
* SIN(RADIANS(gps_latitude))))
AS distance_in_km
FROM table_name as tbl ORDER BY distance_in_km ASC LIMIT 0,1)
UNION ALL
(SELECT tbl.cafe_id , tbl.gps_latitude, tbl.gps_longitude, 111.045 * DEGREES(ACOS(COS(RADIANS(@lat))
* COS(RADIANS(gps_latitude))
* COS(RADIANS(gps_longitude) - RADIANS(@lng))
+ SIN(RADIANS(@lat))
* SIN(RADIANS(gps_latitude))))
AS distance_in_km
FROM table_name as tbl ORDER BY distance_in_km DESC LIMIT 0,1);
执行查询
footer