J'ai l'entrée suivante:
id | value
----+-------
1 | 136
2 | NULL
3 | 650
4 | NULL
5 | NULL
6 | NULL
7 | 954
8 | NULL
9 | 104
10 | NULL
J'attends le résultat suivant:
id | value
----+-------
1 | 136
2 | 136
3 | 650
4 | 650
5 | 650
6 | 650
7 | 954
8 | 954
9 | 104
10 | 104
La solution triviale serait de joindre les tables avec une <
relation, puis de sélectionner la MAX
valeur dans a GROUP BY
:
WITH tmp AS (
SELECT t2.id, MAX(t1.id) AS lastKnownId
FROM t t1, t t2
WHERE
t1.value IS NOT NULL
AND
t2.id >= t1.id
GROUP BY t2.id
)
SELECT
tmp.id, t.value
FROM t, tmp
WHERE t.id = tmp.lastKnownId;
Cependant, l'exécution triviale de ce code créerait en interne le carré du compte des lignes de la table d'entrée ( O (n ^ 2) ). Je m'attendais à ce que t-sql l'optimise - au niveau bloc / enregistrement, la tâche à faire est très facile et linéaire, essentiellement une boucle for ( O (n) ).
Cependant, lors de mes expériences, le dernier MS SQL 2016 ne peut pas optimiser correctement cette requête, ce qui rend cette requête impossible à exécuter pour une grande table d'entrée.
De plus, la requête doit s'exécuter rapidement, ce qui rend impossible une solution basée sur un curseur similaire (mais très différente).
L'utilisation d'une table temporaire sauvegardée en mémoire pourrait être un bon compromis, mais je ne sais pas si elle peut être exécutée beaucoup plus rapidement, étant donné que mon exemple de requête utilisant des sous-requêtes n'a pas fonctionné.
Je pense également à déterrer une fonction de fenêtrage des documents t-sql, ce qui pourrait être trompé pour faire ce que je veux. Par exemple, la somme cumulée fait des choses très similaires, mais je ne pouvais pas le tromper pour donner le dernier élément non nul, et non la somme des éléments précédents.
La solution idéale serait une requête rapide sans code procédural ni tables temporaires. Alternativement, une solution avec des tables temporaires est également correcte, mais itérer la table de manière procédurale ne l'est pas.
la source