WerteTabelle
| Betriebsstunden | Verbrauch |
| 1 | 1,8 |
| 2 | 4,6 |
| 3 | 6,8 |
| 4 | 7,7 |
| 5 | 9,0 |
| 6 | 12,3 |
| 7 | 14,8 |
| 8 | 15,9 |
| Betriebsstunden | Verbrauch | Minus | Verbrauch Zeile vorher | ist | Verbrauch pro Stunde |
| 1 | 1,8 | - | 0,0 | = | 1,8 |
| 2 | 4,6 | - | 1,8 | = | 2,8 |
| 3 | 6,8 | - | 4,6 | = | 2,2 |
| 5 | 7,7 | - | 6,8 | = | 0,9 |
| 6 | 9,0 | - | 7,7 | = | 1,3 |
| 7 | 12,3 | - | 9,0 | = | 3,3 |
| 8 | 14,8 | - | 12,3 | = | 2,5 |
| 9 | 15,9 | - | 14,8 | = | 1,1 |
Wie mach man das mit SQL?
Mein erster "Reflex" einer Lösung ging über ein CURSOR in einer Stored Procedure. Dies klappt natürlich auch. Besinnt man sich aber darauf, dass SQL eine Mengenabfragesprache ist, so kann man eine elegantere Lösung finden. Wir haben zwei Mengen. Unserer Ausgangstabelle und die Menge der Ausgangstabelle um eine Zeile verschoben. Wir JOINen beide Mengen und subtrahieren die Verbrauchswerte
Wie aber nun einen JOIN auf die Zeile vorher machen?
Seit SQL 2005 gibt es die TSQL Funktion ROW_NUMBER. Sie gibt als Integer die Nummer der Zeile zurück. Wir können den erforderlichen JOIN auf die Zeile vorher durchführen, indem in der zweiten Menge die ROW_Number minus 1 zurückgeben:
| Menge von Spalte Verbrauch mit ROW_Number
| Menge von Spalte Verbrauch mit ROW_Number minus 1
| ||||||||||||||||||||||||||||||||||||||||
JOIN von ROW_NUMBER auf ROW_NUMBER minus 1
| |||||||||||||||||||||||||||||||||||||||||
Mit einer CTE können wir nun das Ergebnis gleich in einem Rutsch ausgeben:
WITH WerteTabelle(Betriebsstunden, Verbrauch)
AS
(
SELECT Betriebsstunden = 1, Verbrauch = 1.8 UNION
SELECT Betriebsstunden = 2, Verbrauch = 4.6 UNION
SELECT Betriebsstunden = 3, Verbrauch = 6.8 UNION
SELECT Betriebsstunden = 4, Verbrauch = 7.7 UNION
SELECT Betriebsstunden = 5, Verbrauch = 9.0 UNION
SELECT Betriebsstunden = 6, Verbrauch = 12.3 UNION
SELECT Betriebsstunden = 7, Verbrauch = 14.8 UNION
SELECT Betriebsstunden = 8, Verbrauch = 15.9
)
,Menge1(Nr, Betriebsstunden, Verbrauch)
AS
(
SELECT
-- Zeilennummer
ROW_NUMBER() OVER (ORDER BY Betriebsstunden) AS 'Nr',
Betriebsstunden,
Verbrauch
FROM WerteTabelle
)
,Menge2(NrMinusEins, Betriebsstunden, Verbrauch)
AS
(
SELECT
-- Zeilennummer minus 1
(ROW_NUMBER() OVER (ORDER BY Betriebsstunden) - 1) AS 'NrMinusEins',
Betriebsstunden,
Verbrauch
FROM WerteTabelle
)
SELECT
Menge1.Betriebsstunden,
Menge1.Verbrauch,
Menge2.Verbrauch AS 'Verbrauch Zeile Vorher',
Menge2.Verbrauch - Menge1.Verbrauch AS 'Verbrauch pro Stunde'
FROM
Menge1
-- JOIN Zeilennummer auf Zeilennummer minus 1
INNER JOIN Menge2 ON Menge1.Nr = Menge2.NrMinusEins