Voor dit soort zoekopdrachten profiteert u van aanzienlijke prestatievoordelen door een kalendertabel te maken met elke datum die u ooit zult moeten testen. (Als u bekend bent met de term 'dimensietabellen', is dit slechts zo'n tabel om elke interessante datum op te sommen.)
Ook kan de vraag als geheel aanzienlijk eenvoudiger worden.
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'
;
BEWERKEN Reageer op je opmerking met een andere eis
Het is gemakkelijker om altijd "de waarde hierboven" te krijgen, en om die waarden in een tabel in te voegen is eenvoudig genoeg...
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
;
Opmerking: U kunt WHERE prev_data.gap > 0
. toevoegen naar de grotere zoekopdracht hierboven om alleen datums te krijgen die nog geen gegevens bevatten.