Spring til indhold
Academi.dk

SQL

GROUP BY og aggregering

Let øvet DA↔EN-ordliste

GROUP BY samler rækker med samme værdi til én række, så du kan regne på hver gruppe med COUNT, SUM eller AVG. WHERE filtrerer rækkerne før grupperingen, og HAVING filtrerer grupperne bagefter.

Forudsætter, at du har set where - filtrér rækker .

Fra mange rækker til én pr. gruppe

SELECT kategori, COUNT(*) AS antal, AVG(pris) AS snitpris
FROM produkt
GROUP BY kategori;

Alle rækker med samme kategori bliver til én række i resultatet, og aggregatfunktionerne regner på hver gruppe for sig.

De fem funktioner, du får brug for:

FunktionGiver
COUNT(*)antal rækker i gruppen
COUNT(kolonne)antal rækker hvor kolonnen ikke er NULL
SUM(kolonne)sum
AVG(kolonne)gennemsnit
MIN / MAXmindste og største

Forskellen på COUNT(*) og COUNT(kolonne) er værd at kunne: den sidste tæller ikke tomme værdier med.

Reglen om SELECT-listen

Det her er den fejl, alle får første gang:

-- virker ikke
SELECT kategori, navn, COUNT(*)
FROM produkt
GROUP BY kategori;

Fejlen lyder i stil med “column ‘navn’ is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause”.

Årsagen er logisk, når man ser den: gruppen “kaffe” indeholder tredive produkter med tredive forskellige navne. Hvilket ét af dem skulle databasen vise? Enten skal kolonnen med i GROUP BY, eller også skal den ind i en aggregatfunktion som MAX(navn).

WHERE før, HAVING efter

SELECT kategori, COUNT(*) AS antal
FROM produkt
WHERE aktiv = 1
GROUP BY kategori
HAVING COUNT(*) > 5
ORDER BY antal DESC;
  • WHERE aktiv = 1 fjerner rækker, før de grupperes.
  • HAVING COUNT(*) > 5 fjerner grupper, efter de er dannet.

Du kan ikke skrive WHERE COUNT(*) > 5. Antallet findes ikke endnu på det tidspunkt. Det er den samme rækkefølge som i SELECT: FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY.

Gruppering sammen med JOIN

Den mest almindelige rigtige opgave kombinerer de to:

SELECT k.navn, COUNT(o.id) AS antal_ordrer, SUM(o.total) AS omsaetning
FROM kunde AS k
LEFT JOIN ordre AS o ON o.kunde_id = k.id
GROUP BY k.id, k.navn
HAVING COUNT(o.id) > 0
ORDER BY omsaetning DESC;

To detaljer, der er værd at bemærke: der grupperes på k.id og ikke kun på navnet (to kunder kan hedde det samme), og der bruges COUNT(o.id) frem for COUNT(*), så en kunde uden ordrer tælles som 0 og ikke som 1.

Kort opsamling

  • GROUP BY samler rækker, aggregatfunktioner regner på grupperne.
  • Alt i SELECT skal enten være grupperet eller aggregeret.
  • WHERE før gruppering, HAVING efter.
  • Kontrollér altid en sum mod et eksempel, du kender svaret på.

Læs videre

Senest gennemgået .