Ну, первое отставание не может быть инструментом для работы. Это может быть легче решить с помощью рекурсивного CTE. Sql и оконные функции работают над множеством. Тем не менее, наша цель здесь состоит в том, чтобы придумать способ описания того, что мы хотим. Мы хотели бы разделить наши данные так, чтобы последовательные острова одного и того же значения были частью одного набора.
Один из способов сделать это - использовать lag
, чтобы помочь нам определить, был ли предыдущий ряд другим или нет.
Оттуда теперь мы можем иметь промежуточную сумму по этим событиям изменения для создания разделов. Когда у нас есть разделы, мы можем назначить номер строки каждому элементу в разделе. Наконец, когда у нас есть это, мы можем теперь использовать номер строки, чтобы посмотреть
назад, что много элементов.
;with d as (
select * from (values
(1,4)
,(2,2)
,(3,3)
,(4,3)
,(5,3)
,(6,1)
,(7,4)
,(8,4)
)f(id,source))
select *,lag(source,rn) over (order by Id)
from (
select *,rn=row_number() over (partition by partition_id order by id)
from (
select *, partition_id = sum(change) over (order by id)
from (
select *,change = iif(lag(source) over (order by id) != source,1,0)
from d
) source_with_change
) partitioned
) row_counted
Кстати, это абсолютно жестокий вопрос для собеседования, который мне когда-то задавали.