Ho il seguente input:
id | value
----+-------
1 | 136
2 | NULL
3 | 650
4 | NULL
5 | NULL
6 | NULL
7 | 954
8 | NULL
9 | 104
10 | NULL
Mi aspetto il seguente risultato:
id | value
----+-------
1 | 136
2 | 136
3 | 650
4 | 650
5 | 650
6 | 650
7 | 954
8 | 954
9 | 104
10 | 104
La banale soluzione sarebbe unire le tabelle con una <
relazione e quindi selezionare il MAX
valore in 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;
Tuttavia, la banale esecuzione di questo codice creerebbe internamente il quadrato del conteggio delle righe della tabella di input ( O (n ^ 2) ). Mi aspettavo che t-sql lo ottimizzasse - a livello di blocco / record, l'attività da svolgere è molto semplice e lineare, essenzialmente un ciclo for ( O (n) ).
Tuttavia, nei miei esperimenti, l'ultimo MS SQL 2016 non è in grado di ottimizzare correttamente questa query, rendendo impossibile eseguire questa query per una tabella di input di grandi dimensioni.
Inoltre, la query deve essere eseguita rapidamente, rendendo impossibile una soluzione altrettanto semplice (ma molto diversa) basata sul cursore.
L'uso di una tabella temporanea supportata dalla memoria potrebbe essere un buon compromesso, ma non sono sicuro che possa essere eseguito in modo significativamente più rapido, considerato che la mia query di esempio che utilizza le subquery non ha funzionato.
Sto anche pensando di estrarre alcune funzioni di windowing dai documenti t-sql, cosa potrebbe essere indotto a fare ciò che voglio. Ad esempio, la somma cumulativa sta facendo qualcosa di molto simile, ma non ho potuto ingannarlo per fornire l'ultimo elemento non nullo e non la somma degli elementi precedenti.
La soluzione ideale sarebbe una query veloce senza codice procedurale o tabelle temporanee. In alternativa, anche una soluzione con tabelle temporanee va bene, ma non è iterare proceduralmente la tabella.