Zusammenfassen von Daten mit GROUP BY

Abgeschlossen

Während Aggregatfunktionen für die Analyse nützlich sind, können Sie Ihre Daten in Teilmengen anordnen, bevor Sie sie zusammenfassen. In diesem Abschnitt erfahren Sie, wie Sie dies mithilfe der GROUP BY-Klausel erreichen.

Verwenden der GROUP BY-Klausel

Wie Sie gelernt haben, wird nach der Auswertung der FROM-Klausel und der WHERE-Klausel eine virtuelle Tabelle erstellt, wenn Ihre SELECT-Anweisung verarbeitet wird. Der Inhalt der virtuellen Tabelle steht nun zur weiteren Verarbeitung zur Verfügung. Sie können die GROUP BY-Klausel verwenden, um den Inhalt dieser virtuellen Tabelle in Zeilengruppen zu unterteilen.

Um Zeilen zu gruppieren, geben Sie ein oder mehrere Elemente in der GROUP BY-Klausel an:

GROUP BY <value1> [, <value2>, …]

GROUP BY erstellt Gruppen und platziert Zeilen gemäß den in der Klausel angegebenen Elementen in jeder Gruppe.

Die folgende Abfrage führt beispielsweise zu einer Gruppe gruppierter Zeilen, einer Zeile pro CustomerID in der Tabelle "Sales.SalesOrderHeader ". Eine weitere Möglichkeit zum Betrachten des GROUP BY-Prozesses besteht darin, dass alle Zeilen mit demselben Wert für CustomerID gruppiert und in einer einzelnen Ergebniszeile zurückgegeben werden.

SELECT CustomerID
FROM Sales.SalesOrderHeader
GROUP BY CustomerID;

Die obige Abfrage entspricht der folgenden Abfrage:

SELECT DISTINCT CustomerID
FROM Sales.SalesOrderHeader

Nachdem die GROUP BY-Klausel verarbeitet wurde und jede Zeile einer Gruppe zugeordnet wurde, müssen spätere Phasen der Abfrage alle Elemente der Quellzeilen aggregieren, die sich in der SELECT-Liste befinden, aber nicht in der GROUP BY-Liste angezeigt werden. Diese Anforderung wirkt sich darauf aus, wie Sie Ihre SELECT- und HAVING-Klauseln schreiben.

Was ist also der Unterschied zwischen dem Schreiben der Abfrage mit einer GROUP BY oder einer DISTINCT? Wenn Sie nur die unterschiedlichen Werte für CustomerID kennen möchten, gibt es keinen Unterschied. Mit GROUP BY können wir der SELECT-Liste jedoch weitere Elemente hinzufügen, die dann für jede Gruppe aggregiert werden.

Die einfachste Aggregatfunktion ist ANZAHL(*). Die folgende Abfrage verwendet die ursprünglichen 830 Quellzeilen von CustomerID und gruppiert sie basierend auf den CustomerID-Werten in 89 Gruppen. Jeder unterschiedliche CustomerID-Wert generiert eine Ausgabezeile in der GROUP BY-Abfrage.

SELECT CustomerID, COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID;

Für jeden CustomerID-Wert werden die Zeilen aggregiert und gezählt. Das Ergebnis zeigt, wie viele Zeilen in der Tabelle SalesOrderHeader zu den einzelnen Kunden gehören.

Kunden-ID

Bestellanzahl

1234

3

1005

1

Beachten Sie, dass GROUP BY die Reihenfolge der Ergebnisse nicht garantiert. Häufig werden die Ergebnisse aufgrund der Art und Weise, wie der Gruppierungsvorgang vom Abfrageprozessor ausgeführt wird, in der Reihenfolge der Gruppenwerte zurückgegeben. Sie sollten sich jedoch nicht auf dieses Verhalten verlassen. Wenn die Ergebnisse sortiert werden müssen, müssen Sie explizit eine ORDER-Klausel einschließen:

SELECT CustomerID, COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID
ORDER BY CustomerID;

Dieses Mal werden die Ergebnisse in der angegebenen Reihenfolge zurückgegeben:

Kunden-ID

Bestellanzahl

1005

1

1234

3

Die Klauseln in einer SELECT-Anweisung werden in der folgenden Reihenfolge angewendet:

  1. FROM
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. ORDER BY

Spaltenaliasen werden in der SELECT-Klausel zugewiesen, die nach der GROUP BY-Klausel, aber vor der ORDER BY-Klausel auftritt. Sie können in der ORDER BY-Klausel auf einen Spaltenalias verweisen, jedoch nicht in der GROUP BY-Klausel. Die folgende Abfrage führt zu einem fehler bei ungültigen Spaltennamen :

SELECT CustomerID AS Customer,
       COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY Customer
ORDER BY Customer;

Die folgende Abfrage ist jedoch erfolgreich, gruppiert und sortiert die Ergebnisse nach der Kunden-ID.

SELECT CustomerID AS Customer,
       COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID
ORDER BY Customer;

Problembehandlung bei GROUP BY-Fehlern

Ein häufiges Hindernis, um sich mit der Verwendung von GROUP BY in SELECT-Anweisungen vertraut zu machen, ist das Verständnis dafür, warum die folgende Art von Fehlermeldung auftritt:

Msg 8120, Level 16, State 1, Line 2 Column <column_name> ist in der Auswahlliste ungültig, da sie weder in der Aggregatfunktion noch in der „GROUP BY“-Klausel enthalten ist.

Die folgende Abfrage ist beispielsweise zulässig, da jede Spalte in der SELECT-Liste entweder eine Spalte in der GROUP BY-Klausel oder eine Aggregatfunktion ist, die in jeder Gruppe ausgeführt wird:

SELECT CustomerID, COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID;

Die folgende Abfrage gibt einen Fehler zurück, da PurchaseOrderNumber nicht Teil der GROUP BY-Funktion ist und nicht mit einer Aggregatfunktion verwendet wird.

SELECT CustomerID, PurchaseOrderNumber, COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID;

Diese Abfrage gibt den Fehler zurück:

Msg 8120, Level 16, State 1, Line 1
Column 'Sales.SalesOrderHeader.PurchaseOrderNumber' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

Hier ist eine weitere Möglichkeit, darüber nachzudenken. Diese Abfrage gibt eine Zeile für jeden CustomerID-Wert zurück. Aber Zeilen für dieselbe CustomerID können unterschiedliche PurchaseOrderNumber-Werte aufweisen, sodass welche der Werte die werte sind, die zurückgegeben werden sollen?

Wenn Sie Bestellungen pro Kunden-ID und pro Bestellung anzeigen möchten, können Sie der GROUP BY-Klausel die Spalte "PurchaseOrderNumber " wie folgt hinzufügen:

SELECT CustomerID, PurchaseOrderNumber, COUNT(*) AS OrderCount
FROM Sales.SalesOrderHeader
GROUP BY CustomerID, PurchaseOrderNumber;

Diese Abfrage gibt eine Zeile für jeden Kunden und jede Auftragskombination zusammen mit der Anzahl der Bestellungen für diese Kombination zurück.