Para esses tipos de consulta, você obtém benefícios de desempenho significativos ao criar uma tabela de calendário contendo todas as datas que você precisará testar. (Se você estiver familiarizado com o termo "tabelas de dimensão", esta é apenas uma dessas tabelas para enumerar todas as datas de interesse.)
Além disso, a consulta como um todo pode se tornar significativamente mais simples.
SELECT
cal.calendar_date AS data_date,
CASE WHEN prev_data.gap <= next_data.gap
THEN prev_data.data_value
ELSE COALESCE(next_data.data_value, prev_data.data_value)
END
AS data_value
FROM
calendar AS cal
OUTER APPLY
(
SELECT TOP(1)
data_date,
data_value,
DATEDIFF(DAY, data_date, cal.calendar_date) AS gap
FROM
data_table
WHERE
data_date <= cal.calendar_date
ORDER BY
data_date DESC
)
prev_data
OUTER APPLY
(
SELECT TOP(1)
data_date,
data_value,
DATEDIFF(DAY, cal.calendar_date, data_date) AS gap
FROM
data_table
WHERE
data_date > cal.calendar_date
ORDER BY
data_date ASC
)
next_data
WHERE
cal.calendar_date BETWEEN '2015-01-01' AND '2015-12-31'
;
EDITAR Responda ao seu comentário com um requisito diferente
Obter sempre "o valor acima" é mais fácil, e inserir esses valores em uma tabela é bastante fácil ...
INSERT INTO
data_table
SELECT
cal.calendar_date,
prev_data.data_value
FROM
calendar AS cal
CROSS APPLY
(
SELECT TOP(1)
data_date,
data_value
FROM
data_table
WHERE
data_date <= cal.calendar_date
ORDER BY
data_date DESC
)
prev_data
WHERE
cal.calendar_date BETWEEN '2015-01-01' AND '2015-12-31'
AND cal.calendar_date <> prev_data.data_date
;
Observação: Você pode adicionar
WHERE prev_data.gap > 0
para a consulta maior acima para obter apenas as datas que ainda não têm dados.