我有2个表,其中一个是位置(资产,时间戳和位置),另一个是状态更改(资产,时间戳和状态)。我正在尝试选择所有位置,并加入“当前状态”,该位置由位置时间戳(status.timestamp <= location.timestamp)之前的最新状态更改确定。
Locations
ID Asset Timestamp Lat/Lon
1 A 1000 Lat/Lon
2 A 2000 Lat/Lon
3 A 3000 Lat/Lon
Status
ID Asset Timestamp Status
1 A 1000 active
2 A 2200 sleep
我正在寻找的东西:
LocID Asset Timestamp Lat/Lon Status
1 A 1000 Lat/Lon active
2 A 2000 Lat/Lon active
3 A 3000 Lat/Lon sleep
我知道“连接最近的一行”问题已被问过1000次,但是我对此问题的解决方案在这里不起作用。在这种情况下,我不仅要查找最新的行,还需要与位置表中的时间戳相对应的最新状态...而这超出了我的能力范围。
MariaDB 10.4.12
提前感谢您的帮助!
编辑:使用下面的row_number()的建议确实可以解决问题,但效率不高。在我的完整数据集上运行查询,它超时。有没有解决这个问题的方法?
答案 0 :(得分:1)
在MySQL 8.x中,您可以使用ROW_NUMBER()
窗口函数来过滤相关行。
例如:
select loc_id, asset, timestamp
from (
select
l.id as loc_id,
l.asset,
l.timestamp,
row_number() over(partition by l.asset order by s.timestamp desc) as rn
from locations l
join status s on s.asset = l.asset and s.timestamp <= l.timestamp
) x
where rn = 1
whiteatom编辑: 为了将来的读者-这行得通。我只需要更改分区依据(重新启动编号;就像分组依据一样)。一旦将其更改为“按l.asset,l.timestamp分区”,它将在每个新位置的时间戳记重新开始编号,并且编号为1的行都是正确的。
工作示例:
select loc_id, lts, asset, location, status
from (
select
l.id as loc_id,
l.asset,
l.timestamp as lts,
l.location,
s.status,
row_number() over(partition by l.asset, l.timestamp order by s.timestamp desc) as rn
from location l
join status s on s.asset = l.asset and s.timestamp <= l.timestamp
) x
where rn = 1