In Excel mal eben. SQL und die vorherige Zeile
In Excel kann man nun wirklich mal eben innerhalb einer Formel auf einen Wert in der vorherigen Zeile referenzieren. Ein Klick, fertig. In SQL fängt man mit Slef-Joins und dergleichen an und verliert schnell Lust und Überblick. Muss das?
Nein, zumindest in ORACLE PL/SQL gibt ein passendes Werkzeug: Die LAG Funktion.
Stellen wir uns eine Liste mit Terminen vor. In jeder Zeile haben wir einen konkreten Termin. In der vorherigen Zeile befindet sich der letzte Termin – in der nächsten Zeile wäre dann der folgende Termin. Und wir sollen (wollen) nun die Zeiträume berechnen.
SELECT
t.termin
FROM
termine t
;
Wie kommen wir nun an den Termin der jeweils vorherigen Zeile?
LAG (
feld
[, offset]
[, default]
)
OVER (
[PARTITION BY gruppenfeld]
ORDER BY reihenfolge
)
So. Das sieht jetzt erst einmal ziemlich kompliziert aus. Deshalb unsere konkrete Lösung:
SELECT
t.termin,
LAG ( t.termin, 1 )
OVER ( ORDER BY t.termin ) AS vorheriger_termin
FROM
termine t;
Gib mir einen vorherigen Wert (LAG) für die Spalte t.termin und zwar eine (1) Zeile oberhalb.
Diese eine Zeile oberhalb ergibt sich dadurch (OVER), dass die Liste nach t.termin sortiert ist (ORDER BY t.termin).
Die LAG Klausel muss man als völlig unabhängig vom restlichen SQL Befehl verstehen. Darum benötigt sie verpflichtend eine ORDER BY Klausel um die Reihenfolge der Zeilen festzulegen.
Den Parameter default haben wir ausgelassen. Da die erste Zeile ja logischerweise keine vorherige besitzt, wäre für den ersten Termin vorheriger_termin = NULL. Da wir ja den Zeitraum zwischen den Terminen ausrechnen wollen, wäre es für unser Anliegen sinnvoll, dass der erste Termin seinen eigenen Wert als vorherigen hat (somit wäre die Differenz 0). Dies ergänzen wir noch:
SELECT
t.termin,
LAG ( t.termin, 1, t.termin )
OVER ( ORDER BY t.termin ) AS vorheriger_termin
FROM
termine t
;
Jetzt haben wir also zwei Spalten. Den Termin und den vorherigen Termin. Dann brauchen wir nur noch die Differenz als dritte Spalte berechnen:
SELECT
t.termin,
LAG ( t.termin, 1, t.termin )
OVER ( ORDER BY t.termin ) AS vorheriger_termin,
t.termin-LAG ( t.termin, 1, t.termin )
OVER ( ORDER BY t.termin ) AS tage_differenz
FROM
termine t
;
Man kann noch viele tolle Dinge mit der LAG-Funktion in Oracle’s PL/SQL machen. Das Gegenteil ist übrigens die LEAD Funktion, welche einen Wert aus einer folgenden Zeile liefert.