mysql 计算返回位置的距离
mysql calculate distance for returnning location
这不是以下内容的副本:
Find distance between two points using latitude and longitude in mysql
I tried the query and it's not working, I get empty data set and 0 as
the answer.
SEE answer, THAT is the solution, I don't know why this question was marked as duplicate from Shadow
我有一个 table 结构如下:
table: distance
id int(10) primary key
lat float,
lon float,
time timestamp
我有一个 android 应用程序可以 ping 我的服务器并在每次更改位置时添加一条记录。
例如
id:1, lat:40.753979, lon:-111.881721, time = 1571004620
id:2, lat:40.753979, lon:-111.883721, time = 1571004630
id:3, lat:40.753979, lon:-111.885721, time = 1571004640
如果我走一个方向,我可以计算出总距离:
/* in my python script*/
startLat,startLon = select lat,lon from distance where time >= 1571004620 order by time limit 1;
endLat,endLon = select lat,lon from distance where time <= 1571004640 order by time desc limit limit 1;
然后我可以减去两个坐标,最终得到 0.004000 的经度距离
问题:
如果我添加:
id:4, lat:40.753979, lon:-111.881721, time = 1571004650
那么我应该得到:0.008000
但我得到 0,因为位置 1 与位置 4 相同
您可以利用 MySQL 空间支持,从 5.7 开始可用,以在数据库中执行整个计算。函数 ST_Distance_Sphere()
可用于计算距离。
您实际上需要距离的累加和(这需要 window 函数,自 MySQL 8.0 起可用)。
考虑:
SELECT
id,
time,
SUM(
CASE WHEN lag_lat IS NULL
THEN 0
ELSE ST_Distance_Sphere(point(lag_lon, lag_lat), point(lon, lat))
END
) OVER (ORDER BY time) cumulative_distance
FROM (
SELECT
d.*,
LAG(lat) OVER(ORDER BY time) lag_lat,
LAG(lon) OVER(ORDER BY time) lag_lon
FROM distance d
) x
| id | time | cumulative_distance |
| --- | ---------- | ------------------- |
| 1 | 1571004620 | 0 |
| 2 | 1571004630 | 168.37177423236415 |
| 3 | 1571004640 | 336.7435484657999 |
| 4 | 1571004650 | 673.4870969097663 |
在 MySQL 的早期版本中,您需要模拟 window 函数:
LAG()
可以替换为自身LEFT JOIN
条件NOT EXISTS
和ON
条件[=22]中的相关子查询=]
变量可以模拟累积SUM
查询:
SELECT
id,
time,
@running_distance := @running_distance + CASE
WHEN lag_lat IS NULL THEN 0
ELSE ST_Distance_Sphere(point(lag_lon, lag_lat), point(lon, lat))
END running_distance
FROM (
SELECT
d.id,
d.time,
d.lat,
d.lon,
d_lag.lat lag_lat,
d_lag.lon lag_lon
FROM distance d
LEFT JOIN distance d_lag
ON d_lag.time < d.time
AND NOT EXISTS (
SELECT 1
FROM distance d1
WHERE d1.time < d.time AND d1.time > d_lag.time
)
ORDER BY d.time
) x
CROSS JOIN (SELECT @running_distance := 0) y
Demo on DB Fiddle: 结果同上
这不是以下内容的副本: Find distance between two points using latitude and longitude in mysql
I tried the query and it's not working, I get empty data set and 0 as the answer.
SEE answer, THAT is the solution, I don't know why this question was marked as duplicate from Shadow
我有一个 table 结构如下:
table: distance
id int(10) primary key
lat float,
lon float,
time timestamp
我有一个 android 应用程序可以 ping 我的服务器并在每次更改位置时添加一条记录。
例如
id:1, lat:40.753979, lon:-111.881721, time = 1571004620
id:2, lat:40.753979, lon:-111.883721, time = 1571004630
id:3, lat:40.753979, lon:-111.885721, time = 1571004640
如果我走一个方向,我可以计算出总距离:
/* in my python script*/
startLat,startLon = select lat,lon from distance where time >= 1571004620 order by time limit 1;
endLat,endLon = select lat,lon from distance where time <= 1571004640 order by time desc limit limit 1;
然后我可以减去两个坐标,最终得到 0.004000 的经度距离
问题:
如果我添加:
id:4, lat:40.753979, lon:-111.881721, time = 1571004650
那么我应该得到:0.008000
但我得到 0,因为位置 1 与位置 4 相同
您可以利用 MySQL 空间支持,从 5.7 开始可用,以在数据库中执行整个计算。函数 ST_Distance_Sphere()
可用于计算距离。
您实际上需要距离的累加和(这需要 window 函数,自 MySQL 8.0 起可用)。
考虑:
SELECT
id,
time,
SUM(
CASE WHEN lag_lat IS NULL
THEN 0
ELSE ST_Distance_Sphere(point(lag_lon, lag_lat), point(lon, lat))
END
) OVER (ORDER BY time) cumulative_distance
FROM (
SELECT
d.*,
LAG(lat) OVER(ORDER BY time) lag_lat,
LAG(lon) OVER(ORDER BY time) lag_lon
FROM distance d
) x
| id | time | cumulative_distance |
| --- | ---------- | ------------------- |
| 1 | 1571004620 | 0 |
| 2 | 1571004630 | 168.37177423236415 |
| 3 | 1571004640 | 336.7435484657999 |
| 4 | 1571004650 | 673.4870969097663 |
在 MySQL 的早期版本中,您需要模拟 window 函数:
LAG()
可以替换为自身LEFT JOIN
条件NOT EXISTS
和ON
条件[=22]中的相关子查询=]变量可以模拟累积
SUM
查询:
SELECT
id,
time,
@running_distance := @running_distance + CASE
WHEN lag_lat IS NULL THEN 0
ELSE ST_Distance_Sphere(point(lag_lon, lag_lat), point(lon, lat))
END running_distance
FROM (
SELECT
d.id,
d.time,
d.lat,
d.lon,
d_lag.lat lag_lat,
d_lag.lon lag_lon
FROM distance d
LEFT JOIN distance d_lag
ON d_lag.time < d.time
AND NOT EXISTS (
SELECT 1
FROM distance d1
WHERE d1.time < d.time AND d1.time > d_lag.time
)
ORDER BY d.time
) x
CROSS JOIN (SELECT @running_distance := 0) y
Demo on DB Fiddle: 结果同上