W przypadku tego typu zapytań można uzyskać znaczne korzyści pod względem wydajności, tworząc tabelę kalendarza zawierającą wszystkie daty, które kiedykolwiek będziesz musiał przetestować. (Jeśli znasz termin „tabele wymiarów”, to jest to tylko jedna taka tabela, w której można wymienić wszystkie interesujące Cię daty).
Ponadto zapytanie jako całość może stać się znacznie prostsze.
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'
;
EDYTUJ Odpowiedz na swój komentarz, podając inne wymagania
Aby zawsze uzyskać "powyższą wartość" jest łatwiejsze, a wstawienie tych wartości do tabeli jest wystarczająco łatwe...
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
;
Uwaga: Możesz dodać WHERE prev_data.gap > 0
do większego zapytania powyżej, aby uzyskać tylko daty, które nie mają jeszcze danych.