Я не уверен, что заголовок точно описывает то, что я хочу сделать, но вот рабочий пример, который мне нужно ускорить ...
/*
Aim:
2018-01-01, 1
2018-09-01, 2
2019-01-01, 1
2019-04-01, 3
2020-04-01, 1
2020-09-01, 2
2021-01-01, 1
*/
;WITH temp (ID, GroupID, Date, Value) AS (
SELECT * FROM (VALUES
(1, 1, CAST('2018-01-01' AS DATE), 1),
(2, 1, CAST('2018-04-01' AS DATE), 1),
(3, 1, CAST('2018-09-01' AS DATE), 2),
(4, 1, CAST('2019-01-01' AS DATE), 1),
(5, 1, CAST('2019-04-01' AS DATE), 3),
(6, 1, CAST('2019-09-01' AS DATE), 3),
(7, 1, CAST('2020-01-01' AS DATE), 3),
(8, 1, CAST('2020-04-01' AS DATE), 1),
(9, 1, CAST('2020-09-01' AS DATE), 2),
(10, 1, CAST('2021-01-01' AS DATE), 1),
(11, 2, CAST('2018-01-01' AS DATE), 1),
(12, 2, CAST('2018-04-01' AS DATE), 1),
(13, 2, CAST('2018-09-01' AS DATE), 2),
(14, 2, CAST('2019-01-01' AS DATE), 1),
(15, 2, CAST('2019-04-01' AS DATE), 3),
(16, 2, CAST('2019-09-01' AS DATE), 3),
(17, 2, CAST('2020-01-01' AS DATE), 3),
(18, 2, CAST('2020-04-01' AS DATE), 1),
(19, 2, CAST('2020-09-01' AS DATE), 2),
(20, 2, CAST('2021-01-01' AS DATE), 1)
) AS X(ID, GroupID, Date, Value)
)
select t1.* from temp t1
left join temp t2 on t1.GroupID = t2.GroupID
and t1.Value = t2.Value
and t2.Date < t1.Date
and not exists (
select *
from temp t3
where t1.groupID = t3.GroupID
and t3.Value != t1.Value
and t3.Date between t2.Date and t1.Date
)
where t2.ID is null
order by t1.GroupID asc, t1.Date asc
Это возвращает результаты, которые я хочу, но когда я использую реальные данные, запрос действительно медленный. Кажется, это проверка НЕ СУЩЕСТВУЕТ, которая занимает так много времени
Для каждого GroupID я хочу выбрать самую раннюю дату для каждого значения до тех пор, пока не произойдет следующее значение, и я уверен, что должен быть лучший / более быстрый способ сделать это, но не могу придумать один из них в минуту.
Любые предложения приветствуются