CodeGym /Kurse /SQL SELF /Typische Fehler bei der Verwendung von Window Functions

Typische Fehler bei der Verwendung von Window Functions

SQL SELF
Level 30 , Lektion 4
Verfügbar

Jetzt ist es an der Zeit, über die Schwierigkeiten zu sprechen, die bei der Arbeit mit Window Functions auftreten können. Wie so oft beim Programmieren (und im Leben) ist es besser, aus den Fehlern anderer zu lernen. Wir schauen uns typische Fehler an, die Anfänger – und manchmal sogar erfahrene Entwickler – machen, und lernen, wie man sie vermeidet.

Fehler Nr. 1: Falsche Verwendung von PARTITION BY

Einer der häufigsten Fehler ist es, den PARTITION BY-Parameter zu vergessen oder falsch zu setzen, besonders wenn du die Daten in Gruppen aufteilen willst. Ohne ihn behandelt PostgreSQL alle Zeilen als eine große Gruppe, was dazu führen kann, dass die Ergebnisse ganz anders ausfallen als erwartet.

Nehmen wir an, wir haben eine Tabelle sales, die Verkaufsdaten enthält:

id region month total
1 North 2023-01 1000
2 South 2023-01 800
3 North 2023-02 1200
4 South 2023-02 900

Du willst die kumulierte Summe (SUM()) der Verkäufe pro Monat für jede Region berechnen. Du könntest so eine Abfrage schreiben:

SELECT
    region,
    month,
    SUM(total) OVER (ORDER BY month) AS running_total
FROM 
    sales;

Ergebnis:

region month running_total
North 2023-01 1000
South 2023-01 1800
North 2023-02 3000
South 2023-02 3900

Auf den ersten Blick sieht alles gut aus. Aber das Ergebnis entspricht offensichtlich nicht den Erwartungen, weil die kumulierte Summe nicht nach Regionen, sondern für alle Zeilen zusammen berechnet wird. Das Problem ist, dass wir PARTITION BY region vergessen haben.

Korrigierter Code:

SELECT 
    region,
    month,
    SUM(total) OVER (PARTITION BY region ORDER BY month) AS running_total
FROM 
    sales;

Ergebnis:

region month running_total
North 2023-01 1000
North 2023-02 2200
South 2023-01 800
South 2023-02 1700

Jetzt funktioniert alles richtig: Die Daten werden nach Regionen gruppiert und die kumulierte Summe wird für jede Region separat berechnet.

Fehler Nr. 2: Falsche Reihenfolge im ORDER BY

ORDER BY innerhalb von OVER() steuert die Reihenfolge der Zeilen im Fenster. Wenn die Reihenfolge falsch ist, bekommst du unerwartete Ergebnisse.

Du willst die kumulierten Verkaufssummen berechnen, sortiert nach absteigendem Monat. Du könntest so eine Abfrage schreiben:

SELECT
    month,
    total,
    SUM(total) OVER (ORDER BY month DESC) AS running_total
FROM 
    sales;

Ergebnis:

month total running_total
2023-02 1200 1200
2023-02 900 2100
2023-01 1000 3100
2023-01 800 3900

Auf den ersten Blick sieht alles richtig aus, aber schau genau hin: Die Zeilen sind nach Monaten gruppiert, aber die Summen werden wegen der absteigenden Reihenfolge nicht korrekt berechnet. Deshalb sind die Ergebnisse verwirrend.

Korrektur: Schreib die Abfrage um und verwende die richtige Reihenfolge im ORDER BY:

SELECT
    month,
    total,
    SUM(total) OVER (ORDER BY month ASC) AS running_total
FROM 
    sales;

Fehler Nr. 3: Verwendung von Window Functions ohne Indexe

Window Functions arbeiten oft mit großen Datenmengen, und fehlende Indexe auf den Schlüsselfeldern können zu katastrophalem Performanceverlust führen.

Beispiel: Wir haben eine Tabelle large_sales mit Millionen von Zeilen und wollen die Verkaufsränge berechnen:

SELECT
    id,
    total,
    RANK() OVER (ORDER BY total DESC) AS rank
FROM 
    large_sales;

Bei kleinen Datenmengen läuft die Abfrage vielleicht schnell, aber bei großen dauert es ewig.

Korrektur: Leg einen Index auf die Spalte an, die im ORDER BY verwendet wird:

CREATE INDEX idx_total ON large_sales(total DESC);

Jetzt läuft die Abfrage deutlich schneller.

Fehler Nr. 4: Missverständnis des Fensters, das durch ROWS oder RANGE definiert wird

Wenn du ROWS und RANGE verwendest, ist es wichtig zu verstehen, wie sie das Fenster der Zeilen berechnen. Ein falsches Verständnis dieser Schlüsselwörter kann zu unerwarteten Ergebnissen führen.

Beispiel: Du willst den gleitenden Durchschnitt der Verkäufe für den aktuellen und die zwei vorherigen Monate berechnen:

SELECT
    month,
    AVG(total) OVER (ORDER BY month ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM 
    sales;

Wenn du statt ROWS RANGE angibst:

SELECT
    month,
    AVG(total) OVER (ORDER BY month RANGE BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg
FROM 
    sales;

Das Ergebnis wird anders sein, weil RANGE mit Wertebereichen arbeitet und nicht mit einer festen Anzahl von Zeilen.

Fehler Nr. 5: Übermäßiger Einsatz von Window Functions

Wenn du mehrere Window Functions in einer Abfrage verwendest, kann das zu doppelten Berechnungen und schlechter Performance führen.

Beispiel:

SELECT 
    id,
    total,
    SUM(total) OVER (PARTITION BY region) AS region_total,
    SUM(total) OVER (PARTITION BY region) / COUNT(total) OVER (PARTITION BY region) AS region_avg
FROM 
    sales;

Hier werden SUM(total) und COUNT(total) für jede Zeile mehrfach berechnet.

Korrektur: Kürze die Abfrage mit Subqueries oder CTE:

WITH cte_region_totals AS (
    SELECT 
        region,
        SUM(total) AS region_total,
        COUNT(total) AS region_count
    FROM 
        sales
    GROUP BY 
        region
)
SELECT 
    s.id,
    s.total,
    t.region_total,
    t.region_total / t.region_count AS region_avg
FROM 
    sales s
JOIN 
    cte_region_totals t ON s.region = t.region;

Tipps zur Fehlervermeidung

Checke PARTITION BY und ORDER BY: Überprüfe immer, ob das Fenster richtig gesetzt ist.

Indexiere deine Daten: Besonders wenn du Sortierung (ORDER BY) oder Filter verwendest.

Nutze CTE für wiederholte Berechnungen: Das hilft, doppelte Schritte zu vermeiden.

Schau dir den Ausführungsplan an: Verwende EXPLAIN und EXPLAIN ANALYZE, um zu sehen, wie PostgreSQL die Abfrage verarbeitet.

Teste mit echten Daten: Überprüfe, ob die Ergebnisse deinen Erwartungen entsprechen und die Aufgaben korrekt gelöst werden.

1
Umfrage/Quiz
Fenster-Frame einstellen, Level 30, Lektion 4
Nicht verfügbar
Fenster-Frame einstellen
Fenster-Frame einstellen
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION