SQL self join table 以查找符合条件的下一行

SQL self join table to find next row that matches a condition

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

示例(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

我想要的是 returns 所有 DELIVER 事件连同前面的 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 

不过,这个returns没什么

我不明白我做错了什么,我不知道如何继续。也许还有我不知道的更好的方法。我在网上进行了大量搜索,但没有找到任何可以引导我找到解决方案的内容。谁能给我提示?

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

What I want is a query that returns all DELIVER events together with the preceding DEPART (or maybe NEWTRIP) events, to see how long the trip took.

如果我没理解错的话,你可以用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';

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