通过SQL自连接表来查找符合条件的下一行。

问题描述 投票:0回答:1

我有一个表,其中包含了一个车辆跟踪器产生的事件。这个表叫做tMain(因为它是我的主表),这里重要的列是cVehicleId,cFixedId(事件ID)和cDateTime。ID是整数,cDateTime是datetime2(7).cFixedId可以是NEWTRIP(67)、DEPART(63)、STOP(64)、PROCEED(65)和DELIVER(66)中的一个。这通常也是事件产生的顺序.该表包含了一个车队产生的事件。车辆中的跟踪器也提供了DateTime,所以该表一般是按DateTime排序的,但不一定100%(因为跟踪器可能不是100%同步)。每个车辆的事件不会是连续的(因为有许多车辆同时报告),但它们会按时间排序。

例如(针对1辆车)。

cId         cDateTime               cVehicleId  cFixedId
62462946    2020-06-01 15:47:35.000  27         66
62462476    2020-06-01 15:37:58.000  27         65
62461602    2020-06-01 15:14:43.000  27         64
62461422    2020-06-01 15:11:08.000  27         63
62461407    2020-06-01 15:10:47.000  27         67

我想要的是一个查询,将所有的DELIVER事件和前面的DEPART(或者NEWTRIP)事件一起返回,看看这次旅行花了多长时间。这个查询应该是这样的:我试着找到所有的DEPART事件和前面的DEPART(或者NEWTRIP)事件,看看行程用了多长时间。

cVehicleId  cFixedId  cDateTime                cFixedId  cDateTime
27          67        2020-06-01 15:10:47.000  66        2020-06-01 15:47:35.000

我试过找到所有的DEPART事件 然后向前搜索下一个具有相同VehicleId的事件,其EventId为DELIVER. 或者找到所有DELIVER事件,然后往后搜索最近的具有相同VehicleId的DEPART事件。

我已经尝试了很多使用自连接的查询,也考虑过使用LEAD或LAG函数,但我认为这些对我没有帮助。我就是不能让它工作。

我目前有的是。

DECLARE @DEPART int = 63;
DECLARE @DELIVER int = 66;

DECLARE @StartDate  DATE = '2020-05-01';
DECLARE @StopDate   DATE = '2020-05-02';

select * from
(select cVehicleid, cDatetime, cFixedId from tMain where cFixedId = @DEPART and cDateTime > @StartDate and cDateTime < @StopDate) as t1
inner join 
(select top(1) cVehicleId, cDatetime, cFixedId from tMain where cFixedId = @DELIVER and cDateTime > @StartDate and cDateTime < @StopDate order by cDateTime) as t2 on t2.cVehicleId = t1.cVehicleId and t2.cDateTime > t1.cDateTime 

但是,这个结果是: 毫无.

我不知道自己做错了什么,也不知道该如何继续。也许还有更好的方法,但我不知道。我在网上搜了很多资料,但没有找到任何能让我找到解决办法的东西。谁能给我一个提示?

不太重要的额外问题:如果结果能按VehicledId分组就更好了,但这不是绝对的必须。

sql sql-server self-join
1个回答
0
投票

我想要的是一个查询,返回所有的DELIVER事件和前面的DEPART(或者NEWTRIP)事件,看看这个行程花了多长时间。

如果我理解正确的话,你可以使用 apply:

select d.*, previous.*
from tmain d outer apply
     (select top (1) e.*
      from tmain e
      where e.cVehicleId = d.cVehicleId and
            e.cFixedId in ('DEPART', 'NEWTRIP') and
            e.cDateTime < d.cDateTime
      order by e.cDateTime desc
     ) previous
where d.ceventid = 'DELIVER';

为清晰起见,这里使用字符串版本。

© www.soinside.com 2019 - 2024. All rights reserved.