Das Extrahieren einzigartiger Datensätze in SQL ist mit dem massiven Übergang von Organisationen zur Speicherung multidimensionaler Daten zu einer kritischen Aufgabe geworden. Manchmal ist es erforderlich, einzigartige Zeilen anhand einer Kombination mehrerer Spalten auszugeben, manchmal nur anhand eines einzelnen Schlüssels.
Historie der Frage:
Frühere Versionen von SQL boten nur DISTINCT zur Filterung von Duplikaten an. Dann wurden strukturelle Techniken eingeführt, darunter GROUP BY für Aggregationen auf einzigartigen Wertgruppen und Fensterfunktionen wie ROW_NUMBER() für flexiblere Szenarien im Umgang mit Duplikaten, z. B.: Auswahl basierend auf dem "letzten" oder "ersten" Datensatz.
Problem:
DISTINCT arbeitet nur auf der Ebene der Felder im SELECT, während GROUP BY Aggregationen erfordert. Fensterfunktionen ermöglichen fortschrittliche Logik, häufig führt ihre Verwendung jedoch zu Fehlern, wenn die Reihenfolge der Zeilen nicht durchdacht ist. Oft verwechseln Entwickler diese Ansätze, und Fehler führen zu falschen Ergebnissen.
Lösung:
Beispielcode:
Holen Sie sich den letzten Datensatz über Bestellungen für jeden Kunden:
WITH OrdersRank AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY OrderDate DESC) as rn FROM Orders ) SELECT * FROM OrdersRank WHERE rn = 1;
Wichtige Merkmale:
Kann man DISTINCT zusammen mit aggregierten Funktionen ohne GROUP BY verwenden?
Nein, aggregierte Funktionen erfordern eine Gruppierung, andernfalls gibt es einen Syntaxfehler.
SELECT COUNT(DISTINCT CustomerID) -- korrekt SELECT SUM(Amount), DISTINCT CustomerID -- Fehler!
Was passiert, wenn man im GROUP BY nicht alle nicht-aggregierten Felder aus SELECT angibt?
Dies verursacht in den meisten DBMS einen Fehler: Alle Felder im SELECT, außer den aggregierten, müssen im GROUP BY aufgeführt werden.
Kann man Duplikate mit Fensterfunktionen ohne Unterabfrage "entfernen"?
Nein: Die Verwendung von ROW_NUMBER() innerhalb eines SELECT filtert nicht automatisch "Wiederholungen". Eine äußere Abfrage ist erforderlich, um die gewünschten Zeilen auszuwählen.
Wir haben DISTINCT für alle Spalten einer Tabelle mit 20 Millionen Zeilen ausgewählt: Die Abfrage lief stundenlang, das Ergebnis — Timeout oder Leistungsabfall der DB.
Vorteile:
Nachteile:
Wir haben Fensterfunktionen verwendet: Wir erhielten nur den letzten benötigten Datensatz für jeden Kunden in Millisekunden; frühere und wiederholte Daten wurden nicht geladen.
Vorteile:
Nachteile: