Ich habe folgenden Input:
id | value
----+-------
1 | 136
2 | NULL
3 | 650
4 | NULL
5 | NULL
6 | NULL
7 | 954
8 | NULL
9 | 104
10 | NULL
Ich erwarte folgendes Ergebnis:
id | value
----+-------
1 | 136
2 | 136
3 | 650
4 | 650
5 | 650
6 | 650
7 | 954
8 | 954
9 | 104
10 | 104
Die einfache Lösung wäre, die Tabellen mit einer <
Relation zu verknüpfen und dann den MAX
Wert in a auszuwählen 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;
Die einfache Ausführung dieses Codes würde jedoch intern das Quadrat der Anzahl der Zeilen der Eingabetabelle erzeugen ( O (n ^ 2) ). Ich habe erwartet, dass t-sql es optimiert - auf Block- / Record-Ebene ist die Aufgabe sehr einfach und linear, im Wesentlichen eine for-Schleife ( O (n) ).
In meinen Experimenten kann die aktuelle Version von MS SQL 2016 diese Abfrage jedoch nicht ordnungsgemäß optimieren, sodass diese Abfrage für eine große Eingabetabelle nicht ausgeführt werden kann.
Darüber hinaus muss die Abfrage schnell ausgeführt werden, was eine ähnlich einfache (aber sehr unterschiedliche) Lösung auf Cursorbasis unmöglich macht.
Die Verwendung einer speichergestützten temporären Tabelle könnte ein guter Kompromiss sein, aber ich bin nicht sicher, ob sie wesentlich schneller ausgeführt werden kann, da meine Beispielabfrage mit Unterabfragen nicht funktioniert hat.
Ich denke auch darüber nach, eine Fensterfunktion aus den t-sql-Dokumenten herauszusuchen, die ausgetrickst werden könnte, um das zu tun, was ich will. Zum Beispiel funktioniert die kumulative Summe sehr ähnlich, aber ich konnte es nicht austricksen, um das neueste Nicht-Null-Element und nicht die Summe der vorherigen Elemente zu erhalten.
Die ideale Lösung wäre eine schnelle Abfrage ohne Prozedurcode oder temporäre Tabellen. Alternativ ist auch eine Lösung mit temporären Tabellen in Ordnung, die prozedurale Iteration der Tabelle jedoch nicht.