Stellen Sie sich eine Tabelle vor, in der Besuche aufgezeichnet werden
create table visits (
person varchar(10),
ts timestamp,
somevalue varchar(10)
)
Betrachten Sie diese Beispieldaten (Zeitstempel als Zähler vereinfacht)
ts| person | somevalue
-------------------------
1 | bob |null
2 | bob |null
3 | jim |null
4 | bob | A
5 | bob | null
6 | bob | B
7 | jim | X
8 | jim | Y
9 | jim | null
Ich versuche, den letzten Nicht-Null-Wert der Person auf alle zukünftigen Besuche zu übertragen, bis sich dieser Wert ändert (dh der nächste Nicht-Null-Wert wird).
Die erwartete Ergebnismenge sieht folgendermaßen aus:
ts| person | somevalue | carry-forward
-----------------------------------------------
1 | bob |null | null
2 | bob |null | null
3 | jim |null | null
4 | bob | A | A
5 | bob | null | A
6 | bob | B | B
7 | jim | X | X
8 | jim | Y | Y
9 | jim | null | Y
Mein Versuch sieht so aus:
select *,
first_value(somevalue) over (partition by person order by (somevalue is null), ts rows between UNBOUNDED PRECEDING AND current row ) as carry_forward
from visits
order by ts
Hinweis: Der Wert (ein Wert ist null) wird zum Sortieren mit 1 oder 0 ausgewertet, damit ich den ersten Wert ungleich Null in der Partition erhalten kann.
Das Obige gibt mir nicht das Ergebnis, nach dem ich suche.
postgresql
window-functions
maxTrialfire
quelle
quelle
pg_dump
für Ihre Testdaten einfügen, anstatt die Daten in eine psql-Ausgabe und das Schema für die Tabelle einzufügen?pg_dump -t table -d database
Wir brauchen das Erstellen und dieCOPY
Befehle.Antworten:
Die folgende Abfrage erzielt das gewünschte Ergebnis:
Beachten Sie die Null-Fall-Anweisung - wenn IGNORE_NULL von Postgres-Fensterfunktionen unterstützt würde, wäre dies nicht erforderlich (wie von @ ypercubeᵀᴹ erwähnt).
quelle
count(somevalue) over (...)
Das Problem liegt in der Kategorie der Lücken und Inseln. Es ist schade, dass Postgres noch nicht
IGNORE NULL
in Fensterfunktionen implementiert hat, wieFIRST_VALUE()
es sonst trivial wäre, mit einer einfachen Änderung in Ihrer Abfrage.Es gibt wahrscheinlich viele Möglichkeiten, dies mithilfe von Fensterfunktionen oder rekursiven CTEs zu lösen.
Ich bin mir nicht sicher, ob dies der effizienteste Weg ist, aber ein rekursiver CTE löst das Problem:
quelle