Sammanfatta data med GROUP BY

Slutförd

Aggregerade funktioner är användbara för analys, men du kanske vill ordna dina data i delmängder innan du sammanfattar dem. I det här avsnittet får du lära dig hur du gör detta med hjälp av GROUP BY-satsen.

Använda GROUP BY-satsen

Som du har lärt dig skapas en virtuell tabell när SELECT-instruktionen bearbetas efter att FROM-satsen och WHERE-satsen har utvärderats. Innehållet i den virtuella tabellen är nu tillgängligt för vidare bearbetning. Du kan använda GROUP BY-satsen för att dela upp innehållet i den här virtuella tabellen i grupper med rader.

Om du vill gruppera rader anger du ett eller flera element i GROUP BY-satsen:

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

GROUP BY skapar grupper och placerar rader i varje grupp enligt de element som anges i -satsen.

Följande fråga resulterar till exempel i en uppsättning grupperade rader, en rad per CustomerID i tabellen Sales.SalesOrderHeader . Ett annat sätt att titta på GROUP BY-processen är att alla rader med samma värde för CustomerID grupperas tillsammans och returneras i en enda resultatrad.

SELECT CustomerID
FROM Sales.SalesOrderHeader
GROUP BY CustomerID;

Frågan ovan motsvarar följande fråga:

SELECT DISTINCT CustomerID
FROM Sales.SalesOrderHeader

När GROUP BY-satsen har bearbetats och varje rad har associerats med en grupp måste senare faser av frågan aggregera alla element i källraderna som finns i SELECT-listan men som inte visas i LISTAN GROUP BY. Det här kravet påverkar hur du skriver SELECT- och HAVING-satserna.

Så vad är skillnaden mellan att skriva frågan med en GROUP BY eller en DISTINCT? Om allt du vill veta är de distinkta värdena för CustomerID finns det ingen skillnad. Men med GROUP BY kan vi lägga till andra element i SELECT-listan som sedan aggregeras för varje grupp.

Den enklaste mängdfunktionen är COUNT(*). Följande fråga tar de ursprungliga 830 källraderna från CustomerID och grupperar dem i 89 grupper, baserat på CustomerID-värdena . Varje distinkt CustomerID-värde genererar en rad med utdata i GROUP BY-frågan

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

För varje CustomerID-värde aggregerar och räknar frågan raderna, så resultatet visar oss hur många rader i tabellen SalesOrderHeader som tillhör varje kund.

KundID

AntalBeställningar

1234

3

1005

1

Observera att GROUP BY inte garanterar resultatordningen. Ofta, som ett resultat av hur grupperingsåtgärden utförs av frågeprocessorn, returneras resultaten i ordningen för gruppvärdena. Du bör dock inte förlita dig på det här beteendet. Om du behöver sortera resultaten måste du uttryckligen inkludera en ORDER-sats:

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

Den här gången returneras resultatet i den angivna ordningen:

KundID

AntalBeställningar

1005

1

1234

3

Satserna i en SELECT-instruktion tillämpas i följande ordning:

  1. FRÅN
  2. VAR
  3. GRUPPERA EFTER
  4. ATT HA
  5. VÄLJ
  6. SORTERA EFTER

Kolumnalias tilldelas i SELECT-klausulen, som kommer efter GROUP BY-klausulen men före ORDER BY-klausulen. Du kan referera till ett kolumnalias i ORDER BY-satsen, men inte i GROUP BY-satsen. Följande fråga resulterar i ett ogiltigt kolumnnamnsfel :

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

Följande fråga kommer dock att lyckas och gruppera och sortera resultatet efter kund-ID: t.

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

Felsöka GROUP BY-fel

Ett vanligt hinder för att bli bekväm med att använda GROUP BY i SELECT-instruktioner är att förstå varför följande typ av felmeddelande inträffar:

Msg 8120, Level 16, State 1, Line 2 Column <column_name> är ogiltig i urvalslistan eftersom den inte finns i antingen en mängdfunktion eller GROUP BY-satsen.

Följande fråga är till exempel tillåten eftersom varje kolumn i SELECT-listan antingen är en kolumn i GROUP BY-satsen eller en mängdfunktion som körs i varje grupp:

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

Följande fråga returnerar ett fel eftersom PurchaseOrderNumber inte ingår i GROUP BY och inte används med en mängdfunktion.

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

Den här frågan returnerar felet:

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.

Här är ett annat sätt att tänka på det. Den här frågan returnerar en rad för varje CustomerID-värde . Men rader för samma CustomerID kan ha olika PurchaseOrderNumber-värden , så vilket av värdena är det som ska returneras?

Om du vill se beställningar per kund-ID och inköpsorder kan du lägga till kolumnen PurchaseOrderNumber i GROUP BY-satsen enligt följande:

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

Den här frågan returnerar en rad för varje kund och varje kombination av inköpsorder, tillsammans med antalet beställningar för den kombinationen.