MySQL GROUP BY og HAVING Klausul med eksempler
⚡ Smart opsummering
SQL GROUP BY- og HAVING-klausuler omdanner detaljerede rækker til opsummeringsrapporter. GROUP BY skjuler rækker, der deler de samme værdier, til én række pr. gruppe, mens HAVING filtrerer disse grupper, efter at aggregeringsfunktioner som COUNT er blevet anvendt.
Hvad er SQL GROUP BY-klausulen?
GROUP BY-sætningen er en SQL-kommando, der bruges til grupperækker, der har samme værdierDet er skrevet i SELECT-sætningen, og det bruges normalt sammen med aggregeringsfunktioner til at producere opsummeringsrapporter fra databasen.
Det er, hvad den gør: den opsummerer data opbevares i databasen. Forespørgsler, der indeholder GROUP BY-klausulen, kaldes grupperede forespørgsler, og de returnerer en enkelt række for hvert grupperet element.
SQL GROUP BY Syntaks
Nu hvor formålet med klausulen er klart, kan vi se på syntaksen for en grundlæggende grupperet forespørgsel.
SELECT statements... GROUP BY column_name1[, column_name2, ...] [HAVING condition];
HER
- "SELECT-sætninger…"er standarden SQL SELECT kommandoforespørgsel.
- "GROUP BY kolonnenavn1" er den klausul, der udfører grouping baseret på kolonnenavn1.
- "[, kolonnenavn2, …]" er valgfri og repræsenterer andre kolonnenavne, når gruppenping udføres på mere end én kolonne.
- "[HAVER tilstand]" er valgfri og bruges til at begrænse de rækker, der påvirkes af GROUP BY-klausulen. Det minder om WHERE-klausul, bortset fra at den påføres efter jordenping.
Grouping Brug af en enkelt kolonne
Den hurtigste måde at se effekten af SQL GROUP BY-klausulen på er at sammenligne en ugrupperet forespørgsel med en grupperet. Start med en simpel forespørgsel, der returnerer alle kønsposter i medlemstabellen.
SELECT `gender` FROM `members`;
| køn |
|---|
| Kvinde |
| Kvinde |
| Mand |
| Kvinde |
| Mand |
| Mand |
| Mand |
| Mand |
| Mand |
Ni rækker returneres, og hver værdi gentages. Antag, at vi i stedet ønsker de unikke værdier for køn. Forespørgslen nedenfor tilføjer GROUP BY-klausulen.
SELECT `gender` FROM `members` GROUP BY `gender`;
Udførelse af ovenstående script i MySQL Workbench mod myflixdb giver os følgende resultater.
| køn |
|---|
| Kvinde |
| Mand |
Bemærk, at kun to rækker er blevet returneret, fordi tabellen kun indeholder to kønstyper. GROUP BY-klausulen grupperede alle "Mandlige" medlemmer sammen og returnerede en enkelt række for dem, og den gjorde det samme med "Kvindelige" medlemmer.
Grouping Brug af flere kolonner
Grouping på én kolonne er ofte for grov til en rigtig rapport. GROUP BY accepterer en kommasepareret liste over kolonner, og kombinationen af deres værdier definerer hver gruppe.
Antag, at vi ønsker en liste over værdier for filmkategori-id og de tilsvarende år, hvor filmene blev udgivet. Observer først outputtet fra denne simple forespørgsel.
SELECT `category_id`, `year_released` FROM `movies`;
| kategori_id | år_udgivet |
|---|---|
| 1 | 2011 |
| 2 | 2008 |
| NULL | 2008 |
| NULL | 2010 |
| 8 | 2007 |
| 6 | 2007 |
| 6 | 2007 |
| 8 | 2005 |
| NULL | 2012 |
| 7 | 1920 |
| 8 | NULL |
| 8 | 1920 |
De fremhævede rækker viser, at resultatet indeholder dubletter. Hvis den samme forespørgsel udføres med GROUP BY, fjernes de.
SELECT `category_id`, `year_released` FROM `movies` GROUP BY `category_id`, `year_released`;
Udførelse af ovenstående script i MySQL Workbench mod myflixdb giver os følgende resultater vist nedenfor.
| kategori_id | år_udgivet |
|---|---|
| NULL | 2008 |
| NULL | 2010 |
| NULL | 2012 |
| 1 | 2011 |
| 2 | 2008 |
| 6 | 2007 |
| 7 | 1920 |
| 8 | 1920 |
| 8 | 2005 |
| 8 | 2007 |
GROUP BY-klausulen fungerer på både category_id og year_released for at identificere enestående rækker. De to duplikerede rækker for kategori 6 i 2007 blev slået sammen til én.
Tommelfingerregel: Hvis kategori-id'et er det samme, men udgivelsesåret er forskelligt, behandles rækken som unik. Hvis kategori-id'et og udgivelsesåret er det samme for mere end én række, er rækkerne dubletter, og kun én af dem vises.
Grouping og aggregatfunktioner
Det er nyttigt at fjerne dubletter, men den virkelige kraft ved groupping vises, når den er parret med samlede funktionerEn aggregeringsfunktion beregner én værdi for hver gruppe: COUNT tæller rækker, SUM lægger værdier sammen, og AVG, MIN og MAX beskriver spredningen.
Antag, at vi ønsker det samlede antal mandlige og kvindelige medlemmer i databasen. Scriptet nedenfor gør det.
SELECT `gender`, COUNT(`membership_number`) FROM `members` GROUP BY `gender`;
Udførelse af ovenstående script i MySQL Workbench mod myflixdb giver os følgende resultater.
| køn | ANTAL(`medlemsnummer`) |
|---|---|
| Kvinde | 3 |
| Mand | 6 |
Rækkerne er grupperet efter hver unikke kønsværdi, og antallet af rækker i hver gruppe tælles af den samlede funktion COUNT. De ni medlemsposter samles i to opsummeringsrækker.
Begrænsning af forespørgselsresultater ved hjælp af HAVING-klausulen
Groupings er ikke altid ønskede for hver række i en tabel. Nogle gange skal rapporten begrænses til et givet kriterium, og det er HAVING-klausulens opgave.
Antag, at vi vil kende alle udgivelsesårene for filmkategori-id 8. Scriptet nedenfor opnår dette resultat.
SELECT * FROM `movies` GROUP BY `category_id`, `year_released` HAVING `category_id` = 8;
Udførelse af ovenstående script i MySQL Workbench mod myflixdb giver os følgende resultater vist nedenfor.
| film_id | titel | direktør | år_udgivet | kategori_id |
|---|---|---|---|---|
| 9 | Honey moonERS | John Schultz | 2005 | 8 |
| 5 | Daddy's Little Girls | NULL | 2007 | 8 |
Kun film med kategori-id 8 er blevet gemt af HAVING-betingelsen.
Advarsel: MySQL 5.7 og nyere aktiverer ONLY_FULL_GROUP_BY-tilstanden som standard, og i den tilstand afvises SELECT * med en GROUP BY-klausul, fordi movie_id, titel og instruktør hverken grupperes eller aggregeres. I produktion skal de grupperede kolonner navngives eksplicit, for eksempel VÆLG kategori_id, udgivelsesår FRA film GROUP BY kategori_id, udgivelsesår HAR kategori_id = 8;
HVOR vs. HAVE vs. GROUP BY vs. ORDER BY
Begyndere blander ofte disse fire klausuler, fordi de alle former resultatsættet. Forskellen ligger i hvornår MySQL anvender dem: WHERE køres før rækkerne grupperes, HAVING køres efter, og ORDER BY køres til sidst.
| Klausul | Hvad gør den | Når den kører | Accepterer aggregerede funktioner |
|---|---|---|---|
| HVOR | Filtrerer individuelle rækker før enhver gruppeping. | Før GROUP BY | Ingen |
| GROUP BY | Skjuler rækker, der deler de samme værdier, til én række pr. gruppe. | Efter HVOR | Ikke relevant |
| SOM | Filtrerer de grupper, der er produceret af GROUP BY. | Efter GROUP BY | Ja, for eksempel HAVING COUNT(*) > 2 |
| BESTIL BY | Sorterer de rækker, der overlever de foregående klausuler. | Efternavn | Ja, et samlet alias kan sorteres |
Den praktiske konsekvens er af ydeevnemæssig karakter. Filtrering med WHERE fjerner rækker før gruppenping arbejdet starter, så en betingelse, der ikke afhænger af et aggregeret resultat, hører hjemme i WHERE snarere end HAVING.

