За тези типове заявки получавате значителни предимства в производителността от създаването на календарна таблица, съдържаща всяка дата, която някога ще трябва да тествате. (Ако сте запознати с термина „таблици с размери“, това е само една такава таблица за изброяване на всяка дата, представляваща интерес.)
Също така, заявката като цяло може да стане значително по-проста.
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'
;
РЕДАКТИРАНЕ Отговорете на коментара си с различно изискване
Винаги да получавате "стойността по-горе" е по-лесно и да вмъкнете тези стойности в таблица е достатъчно лесно...
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
;
Забележка: Можете да добавите WHERE prev_data.gap > 0
към по-голямата заявка по-горе, за да получите само дати, които все още нямат данни.