如何解决在 SQL 表上查找每个参与者的速度
我有一个关于几个人的运动的 sql 表 (people_movement),如下所示:
姓名 | 时间 | 位置增量(m) |
---|---|---|
布列塔尼 | 10.20 | -75 |
布列塔尼 | 10.30 | 800 |
布列塔尼 | 10.45 | 800 |
布列塔尼 | 11.00 | 900 |
艾伦 | 10.15 | 400 |
艾伦 | 10.16 | -700 |
艾伦 | 1020 | 800 |
凯西 | 9.50 | 800 |
凯西 | 10.01 | -400 |
凯西 | 10.05 | 200 |
注意是记录了时间,所以对于第一条记录,开始时间未知,但是以一行的时间作为下一行的开始时间。 有数以千计的参与者有不同的行数,有些参与者有 4 或 5 行,但许多参与者有 100 行。 我需要计算他们的移动速度(米/分钟),所以表格看起来像这样:
姓名 | 开始时间 | 结束时间 | 位置增量(m) | 增量速度(米/分钟) |
---|---|---|---|---|
布列塔尼 | - | 10.20 | -75 | - |
布列塔尼 | 10.20 | 10.30 | 800 | 80 |
布列塔尼 | 10.30 | 11.45 | 800 | 53.33 |
布列塔尼 | 10.45 | 11.00 | 900 | 60 |
艾伦 | - | 10.15 | 400 | - |
艾伦 | 10.15 | 10.16 | -700 | -700 |
艾伦 | 10.16 | 10.20 | 800 | 200 |
凯西 | - | 09.50 | 800 | - |
凯西 | 09.50 | 10.01 | -400 | -0.18 |
凯西 | 10.01 | 10.05 | 200 | 50 |
注意增量速度只是(位置增量/(开始时间 - 结束时间)),其中结束时间只是每个参与者(姓名)下一次移动的时间。
有没有办法进行这样的计算?
谢谢
解决方法
使用自连接。
CREATE TABLE speed_test(name varchar(10),time int,position int);
mysql> INSERT INTO speed_test VALUES ('Brittany',1020,-75);
Query OK,1 row affected (0,01 sec)
mysql> INSERT INTO speed_test VALUES ('Brittany',1030,800);
Query OK,00 sec)
mysql> INSERT INTO speed_test VALUES ('Brittany',1045,1100,900);
Query OK,00 sec)
mysql> INSERT INTO speed_test VALUES ('Alan',1015,400);
Query OK,1016,-700);
Query OK,01 sec)
mysql> INSERT INTO speed_test VALUES ('Alan',800);
SELECT t1.name,t2.time as start_time,t1.time as end_time,t1.position,t1.position/(t1.time-t2.time)
FROM speed_test t1
LEFT JOIN
speed_test t2
ON t2.name=t1.name
AND t2.time<t1.time
AND t2.time=(SELECT max(time) FROM speed_test WHERE t1.name=name AND time<t1.time);
+----------+------------+----------+----------+-------------------------------+
| name | start_time | end_time | position | t1.position/(t1.time-t2.time) |
+----------+------------+----------+----------+-------------------------------+
| Brittany | NULL | 1020 | -75 | NULL |
| Brittany | 1020 | 1030 | 800 | 80.0000 |
| Brittany | 1030 | 1045 | 800 | 53.3333 |
| Brittany | 1045 | 1100 | 900 | 16.3636 |
| Alan | NULL | 1015 | 400 | NULL |
| Alan | 1015 | 1016 | -700 | -700.0000 |
| Alan | 1016 | 1020 | 800 | 200.0000 |
+----------+------------+----------+----------+-------------------------------+
速度的差异是因为时间列中的整数与时间。
,由于您的 TimeFormat 是 HH.mm
,您需要分别捕捉小时和分钟。
如果您使用的是 SQL Server
,请尝试以下操作:
Create table #temp
(
Name varchar(100),Time numeric(6,2),Position_Increment int
)
INSERT INTO #temp
values
('Brittany',10.20,-75 ),('Brittany',10.30,800 ),10.45,11.00,900 ),('Alan',10.15,400 ),10.16,-700),('Casey',9.50,10.01,-400),10.05,200 )
;with cte as
(
select Name,Time as EndTime,Position_Increment,Lag(EndTimeHH,1,0) over (partition by Name order by Time ) as StartTimeHH,Lag(EndTimemm,0) over (partition by Name order by Time ) as StartTimemm,StartTime,EndTimeHH,EndTimemm
from
(
select *,SUBSTRING(cast(time as varchar),CHARINDEX('.',time)-1) as EndTimeHH,time)+1,len(time)) as EndTimemm,Lag(Time,0) over (partition by Name order by Time ) as StartTime
from #temp
) as t
)
select Name,CASE WHEN StartTime =0 Then '-' ELSE CAST(StartTime AS varchar) END AS StartTime,EndTime,CASE WHEN StartTime =0
Then '-'
ELSE CAST(Position_Increment /ABS(((StartTimeHH*60+StartTimemm) - (EndTimeHH*60+EndTimemm))) AS varchar)
END AS IncrementSpeed
from cte
order by name
Drop table #temp
,
以下伪代码解释了要做什么:
select name,lag(time) over (partition by name order by time) as start_time,time as end_time,( position_increment /
(time - lag(time) over (partition by name order by time))
) as increment_speed
from t;
一个警告是日期/时间函数在数据库中变化很大,因此您需要使用适当的逻辑来减去两次。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。