ProgrammierungSQL Analyst

Wie kann man aus einer komplexen Datenstruktur mit mehreren Duplikaten in verschiedenen Spalten nur einzigartige Datensätze abrufen, und wie funktioniert DISTINCT vs GROUP BY vs ROW_NUMBER()?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

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:

  • Verwenden Sie DISTINCT, um einzigartige Zeilen basierend auf den benötigten Feldern zu erhalten.
  • GROUP BY — wenn Aggregationen benötigt werden (z. B. Summe oder Datum für einzigartige Paare).
  • Fensterfunktionen (ROW_NUMBER()) — für Aufgaben wie die Auswahl "einer Zeile aus einer Gruppe von Duplikaten nach einem bestimmten Kriterium".

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:

  • DISTINCT — gibt einzigartige Zeilen nur für die im SELECT angegebenen Felder zurück.
  • GROUP BY — ist notwendig, wenn eine Aggregation erforderlich ist.
  • ROW_NUMBER() — ist maximal flexibel für die Auswahl von Zeilen mit der gewünschten Priorität/Daten/Versonierung.

Fangfragen.

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.

Typische Fehler und Anti-Pattern

  • Verwendung von DISTINCT bei einer großen Anzahl von Spalten und Zeilen — drastischer Leistungsabfall.
  • GROUP BY ohne benötigte Aggregation — sinnlos und ressourcenintensiv.
  • Fensterfunktionen ohne anschließenden Filter — Daten werden mit Duplikaten zurückgegeben.

Beispiel aus dem Leben

Negativer Fall

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:

  • Einfach zu schreiben.

Nachteile:

  • Extrem ineffizient bei großen Datenmengen.

Positiver Fall

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:

  • Höchste Leistung.
  • Flexibilität.

Nachteile:

  • Erfordert eine gut durchdachte Abfragenarchitektur und Kenntnisse über Fensterfunktionen.