Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

trouver les entrées manquantes pour les jours ouvrables et remplir la ligne avec les valeurs de la date la plus proche

Pour ces types de requêtes, vous bénéficiez d'avantages significatifs en termes de performances en créant une table de calendrier contenant toutes les dates que vous devrez tester. (Si vous connaissez le terme "tables de dimension", ce n'est qu'une de ces tables pour énumérer chaque date d'intérêt.)

De plus, la requête dans son ensemble peut devenir beaucoup plus simple.

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'
;

MODIFIER Répondre à votre commentaire avec une exigence différente

Obtenir toujours "la valeur ci-dessus" est plus facile, et insérer ces valeurs dans un tableau est assez facile...

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
;

Remarque : Vous pouvez ajouter WHERE prev_data.gap > 0 à la plus grande requête ci-dessus pour obtenir uniquement les dates qui n'ont pas encore de données.