«Правильный» путь - lag(ignore nulls)
, но SQL Сервер пока не реализует это.
Если значения постоянно растут, вы можете использовать совокупный максимум:
select t.*,
max(value) over (partition by key order by date) as new_value
from t;
Это особый случай, остальная часть ответа дает более общие ответы.
Другой метод использует outer apply
:
select t.*, t2.value
from t outer apply
(select top (1) t2.*
from t t2
where t2.key = t.key and t2.date <= t.date and t2.value is not null
order by t2.date desc
) t2
А третий метод использует два уровня окна функции:
select t.*, max(value) over (partition by key, not_null_date)
from (select t.*,
max(case when value is not null then date end) over (partition by key order by date) as not_null_date
from t
) t