SELECT Dep.TimeStamp as Departed, Arr.TimeStamp as Arrived, Dep.LogId as DepartedLogID, Arr.LogId as ArrivedLogID, Dep.msgText as DepartedText, Arr.msgText as ArrivedText, Dep.Train, Dep.Veh1, Dep.Veh2, Dep.Veh3, Dep.tstc as DepartedTSTC, Arr.tstc as ArrivedTSTC, Arr.Dwell as Dwell, datediff(second, Dep.TimeStamp, Arr.TimeStamp) as Interval FROM ( SELECT Dep.[pk] as fkDeparture, Arr.[pk] as fkArrival FROM [SMC].[dbo].[SmcLog] Dep (NOLOCK) CROSS APPLY ( SELECT TOP 1 Arr.[PK] FROM [SMC].[dbo].[SmcLog] Arr (NOLOCK) Where Arr.LogID = 292 and Arr.Train = Dep.Train and Arr.TimeStamp > Dep.TimeStamp -- Find arrival ORDER BY Arr.TimeStamp ASC ) Arr WHERE LogID = 324 and Dep.TimeStamp between @Start and @End -- Find departures ) P JOIN [SMC].[dbo].[SmcLog] Dep on Dep.PK = P.fkDeparture JOIN [SMC].[dbo].[SmcLog] Arr on Arr.PK = P.fkArrival ORDER by Dep.Train, Dep.TimeStamp descThe important query is the inner one (P), where I just get the Primary keys of the table to get the rest of the fields I might want (using the Joins). This query works well, I get the data I need and it is instant for a day and it takes only a couple of seconds for a month (which we will never use, I just use a month to test the speed, as the table has 200 million records and it grows at around 200/400 thousand records per day.
SELECT Dep.TimeStamp as Departed, Arr.TimeStamp as Arrived, Dep.LogId as DepartedLogID, Arr.LogId as ArrivedLogID, Dep.msgText as DepartedText, Arr.msgText as ArrivedText, Dep.Train, Dep.Veh1, Dep.Veh2, Dep.Veh3, Dep.tstc as DepartedTSTC, Arr.tstc as ArrivedTSTC, Arr.Dwell as Dwell, datediff(second, Dep.TimeStamp, Arr.TimeStamp) as Interval, case when Arr.LogID = 292 then 1 else 0 end as isArrival FROM ( SELECT [Dep].[pk] as fkDeparture, [Arr].[pk] as fkArrival FROM [SMC].[dbo].[SmcLog] Dep (NOLOCK) CROSS APPLY ( SELECT TOP 1 [Arr].[PK] FROM [SMC].[dbo].[SmcLog] Arr (NOLOCK) Where Arr.LogID IN (292, 324) and Arr.Train = Dep.Train and Arr.TimeStamp > Dep.TimeStamp -- Find arrival ORDER BY Arr.TimeStamp ASC ) Arr WHERE LogID = 324 and Dep.TimeStamp between @Start and @End -- Find departures ) P JOIN [SMC].[dbo].[SmcLog] Dep on Dep.PK = P.fkDeparture JOIN [SMC].[dbo].[SmcLog] Arr on Arr.PK = P.fkArrival ORDER by Dep.Train, Dep.TimeStamp descThis query will make the second departure an arrival and fix the issue, and is still instantaneous, the problem is that I cannot think of an easy solution for the case where there are two consecutive departures, any ideas?
UNION SELECT [Dep].[pk] as fkDeparture, [Arr].[pk] as fkArrival FROM [SMC].[dbo].[SmcLog] Dep (NOLOCK) CROSS APPLY ( SELECT TOP 1 [Arr].[PK], Arr.LogId FROM [SMC].[dbo].[SmcLog] Arr (NOLOCK) Where Arr.LogID IN (292, 324) and Arr.Train = Dep.Train and Arr.TimeStamp > Dep.TimeStamp -- Find arrival ORDER BY Arr.TimeStamp ASC ) Arr WHERE Dep.LogID = 292 and Arr.LogID = 292 and Dep.TimeStamp between @Start and @End -- Find two consecutive arrivals, then the first one is a departure.I think this will do, to many other things to do to get stuck in aesthetics :)