Теперь, зная, что вы находитесь на SQL Server 2005, вам нужно будет положиться на outer apply
, чтобы выполнить произвольное соединение, необходимое здесь для определения относительной предыдущей записи.
Выне обрисовал в общих чертах предикат здесь.Но, исходя из выходных данных, вы ищете первые WorkOrder
каждой группы, что в данном случае выглядит как прогон времени, пока не появится другое WorkOrder
.
В приведенном ниже подходе используется apply
чтобы получить предыдущую запись, используя top 1
, в частности outer apply
, чтобы гарантировать, что мы не потеряем первую запись (представьте, что это left join
).
Итератор apply
почти всегда игнорируется и часто забывается.Но это очень мощный инструмент, когда вам нужна итерация без конкретного предиката соединения, такого как ключ.Я использовал этот подход для больших таблиц, чтобы решить «проблему топ-n», обнаруживая, что иногда она работает лучше, чем встроенная.
Обратите внимание, что я выбрал No
в качествемой тай-брейк.
CREATE TABLE #WorkOrders (
No INT IDENTITY PRIMARY KEY
,WorkOrder VARCHAR(8) NOT NULL
,StartDateTime DATETIME NOT NULL
,EndDateTime DATETIME NOT NULL);
INSERT INTO #WorkOrders (WorkOrder, StartDateTime, EndDateTime)
VALUES ('WO111111','20190101 07:00','20190101 08:00')
,('WO111111','20190101 08:00','20190101 08:30')
,('WO111111','20190101 08:30','20190101 09:30')
,('WO222222','20190101 08:30','20190101 09:30')
,('WO222222','20190101 09:30','20190101 10:00')
,('WO222222','20190101 10:00','20190101 12:30')
,('WO111111','20190101 12:00','20190101 12:30')
SELECT wo.WorkOrder
, wo.StartDateTime
, wo.EndDateTime
FROM #WorkOrders AS wo
OUTER APPLY (
SELECT TOP(1)
*
FROM #WorkOrders AS wo2
WHERE wo2.StartDateTime < wo.StartDateTime
ORDER BY wo2.StartDateTime DESC, No DESC
) AS prev
WHERE prev.WorkOrder IS NULL
OR prev.WorkOrder <> wo.WorkOrder
DROP TABLE #WorkOrders;