SQL DISTINCT und TOP in derselben Abfrage

Dieser Artikel wurde durch eine Reihe von Fragen inspiriert, die mir Nan, eine meiner Leserinnen, kürzlich zu DISTINCT, TOP und ORDER BY geschickt hat.

Alle Beispiele in dieser Lektion basieren auf Microsoft SQL Server Management Studio und der AdventureWorks2012-Datenbank. Sie können mit diesen kostenlosen Tools beginnen, indem Sie meinen Leitfaden Erste Schritte mit SQL Server verwenden.

Wie arbeiten die SQL-Modifikatoren Top und Distinct SELECT zusammen, um Ergebnisse zu erzeugen?

Hier ist die Frage, die Nan mir ursprünglich geschickt hat:

Ich bin etwas verwirrt über SELECT DISTINCT und SELECT. Zum Beispiel:

SELECT DISTINCT TOP 10 FirstName,
LastName
FROM Person.Person
ORDER BY LastName

Wird nach eindeutigen Vornamen gesucht? Nach eindeutigen kombinierten Vor- und Nachnamen? Wie unterscheiden wir zwischen den Spalten, die für die eindeutige Auswertung verwendet werden, und den Spalten, die wir nur in der Ausgabe anzeigen wollen?

Was ist mit

Select Distinct TOP 10 LastName,
FirstName + ' ' + LastName AS FullName
FROM Person.Person
ORDER BY LastName

Ich dachte, dass jeder die Antwort wissen möchte, also habe ich einen Blogbeitrag erstellt.

DISTINCT und TOP – Was kommt zuerst?

Schauen wir uns die erste Anweisung an, deren Zweck es ist, eine eindeutige Liste von Vor- und Nachnamen zurückzugeben.

SELECT DISTINCT TOP 10 FirstName,
LastName
FROM Person.Person
ORDER BY LastName;

TOP 10 gibt die ersten zehn Elemente aus der geordneten Menge zurück, und DISTINCT entfernt alle Duplikate. Die Frage ist, was zuerst passiert?

  • Ist die Tabelle nach Nachname sortiert, werden die ersten zehn Elemente entnommen und dann die doppelten Namen entfernt?
  • Oder werden die Duplikate entfernt und dann die Elemente sortiert und die ersten zehn Elemente angezeigt?

Bevor wir diese Frage beantworten, denken Sie daran, dass DISTINCT auf alle Spalten und Ausdrücke in der SELECT-Klausel wirkt. In diesem Fall gibt die Anweisung also unterschiedliche Zeilen für Vorname und Nachname zurück.

Leider gibt es keine direkte Möglichkeit, DISTINCT auf eine Gruppe von Feldern anzuwenden und andere anzuzeigen. Sobald Sie der SELECT-Anweisung Spalten hinzufügen, werden diese durch den DISTINCT-Operator beeinflusst. Ich sage direkt, da Sie eine eindeutige Liste erhalten und dann einen INNER JOIN verwenden könnten, um andere Spalten hinzuzuziehen. Dies birgt jedoch Gefahren, da die Verknüpfung erneut Duplikate einführen kann.

Das Hinzufügen einer TOP-Klausel zu DISTINCT ist interessant. Ich war mir nicht sicher, was passieren würde, aber ich habe mit der AdventureWorks-Datenbank experimentiert und festgestellt, dass die Reihenfolge der Verarbeitung in etwa so aussieht:

  1. Wählen Sie DISTINCT-Werte aus der Tabelle aus und ordnen Sie sie an
  2. Wählen Sie die TOP x Zeilen aus den Ergebnissen von Schritt 1 aus und zeigen Sie sie an.

Wenn Sie das selbst ausprobieren möchten, beginnen Sie mit

SELECT FirstName,
LastName
FROM Person.Person
ORDER BY LastName

und beachten Sie die Ergebnisse. Achten Sie auf „Kim Ambercombie“. Beachten Sie, dass es drei Einträge für ihren Namen gibt.

Ergebnisse sortiert nach Nachname

Starten Sie nun mit

SELECT DISTINCT FirstName,
LastName
FROM Person.Person
ORDER BY LastName

Und Sie werden sehen, dass „Kim Ambercombine“ nur einmal angezeigt wird.

Einzigartige Liste sortiert nach Nachname

Dann führen Sie aus

SELECT DISTINCT TOP 10 FirstName,
LastName
FROM Person.Person
ORDER BY LastName

Und Sie werden sehen, dass die ersten 10 eindeutigen Vor- und Nachnamen sortiert nach Nachname angezeigt werden.

Erste 10 eindeutige Zeilen, sortiert nach Nachname

Wenn Sie sich fragen, was zuerst passiert, die DISTINCT- oder TOP 10-Operationen, dann vergleichen Sie die Ergebnisse der letzten beiden Abfragen.

Beachten Sie, dass die Abfrage „DISTINCT TOP 10“ die ersten 10 Zeilen aus der Abfrage der „DISTINCT“-Abfrage enthält.

Aus diesem Grund wissen wir, dass zuerst eine DISTINCT-Liste erstellt wird und dann die TOP 10 Elemente zurückgegeben werden.

Abfrageplan, der die Reihenfolge der Ausführung zeigt

Sie können dies auch bestätigen, indem Sie den Abfrageplan anzeigen. Wählen Sie dazu Abfrage -> Aktuellen Abfrageplan einbeziehen aus dem Menü, bevor Sie die Abfrage ausführen.

Das Symbol „Stream Aggregate“ steht für die DISTINCT-Operation und „Top“ für die TOP 10-Operation.

Es mag etwas kontraintuitiv erscheinen, dass DISTINCT innerhalb der SELECT-Anweisung zuerst aufgeführt wird. Denken Sie einfach daran, dass SQL nicht unbedingt in der Reihenfolge verarbeitet wird, in der ein Mensch es von links nach rechts lesen würde.

DISTINCT und TOP mit SELECT-Listenausdrücken

Der zweite Teil von Nans Frage bezog sich darauf, wie Ausdrücke mit dem DISTINCT-Operator behandelt werden.

Ausdrücke werden in Bezug auf DISTINCT und TOP genauso behandelt wie Spalten. Beginnen wir mit einer Select-Anweisung, um den Vornamen sowie den vollständigen Namen zu erhalten, den wir durch Anhängen von LastName an FirstName erstellen.

Auch bei der Verwendung von ORDER BY ist zu beachten, dass die ORDER BY-Elemente in der Select-Liste erscheinen müssen, wenn Distinct verwendet wird. In Anbetracht dessen muss ich die in der ursprünglichen Frage dargestellte Anweisung ändern:

SELECT DISTINCT FirstName,
FirstName + ' ' + LastName AS FullName
FROM Person.Person
ORDER BY LastName

Wird nicht ausgeführt, da LastName nicht in der SELECT-Liste enthalten ist. Ja, er ist Teil eines Ausdrucks in der Auswahlliste, aber er ist nicht eigenständig vorhanden. Es ist gültig, nach FullName zu sortieren.

Wir werden diese Sortierung in den folgenden Beispielen verwenden.

Die Anweisung

SELECT FirstName,
FirstName + ' ' + LastName AS FullName
FROM Person.Person
ORDER BY FirstName + ' ' + LastName

gibt 19972 Zeilen zurück. Wenn wir Distinct

SELECT DISTINCT FirstName,
FirstName + ' ' + LastName AS FullName
FROM Person.Person
ORDER BY FirstName + ' ' + LastName

hinzufügen, werden 19516 Zeilen zurückgegeben. Wenn man schließlich Top 10 hinzufügt, werden die ersten 10 eindeutigen Namenskombinationen zurückgegeben.

SELECT DISTINCT TOP 10 FirstName,
FirstName + ' ' + LastName AS FullName
FROM Person.Person
ORDER BY FirstName + ' ' + LastName

Versuchen Sie, diese Abfragen in der AdventureWork-Datenbank auszuführen, und Sie werden selbst sehen, dass das Verhalten dasselbe ist wie bei der ausschließlichen Arbeit mit Spalten.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.