MySQL GROUP BY i HAVING klauzula s primjerima
⚡ Pametni sažetak
SQL klauzule GROUP BY i HAVING pretvaraju detaljne retke u sažeta izvješća. GROUP BY sažima retke koji dijele iste vrijednosti u jedan redak po grupi, dok HAVING filtrira te grupe nakon što su primijenjene agregacijske funkcije poput COUNT.

Što je SQL GROUP BY klauzula?
Klauzula GROUP BY je SQL naredba koja se koristi za grupirati retke koji imaju iste vrijednostiNapisuje se unutar SELECT naredbe i obično se koristi zajedno s agregacijskim funkcijama za izradu sažetih izvješća iz baze podataka.
To je ono što radi: to sažima podatke pohranjenih u bazi podataka. Upiti koji sadrže klauzulu GROUP BY nazivaju se grupirani upiti i vraćaju jedan redak za svaku grupiranu stavku.
SQL GROUP BY Sintaksa
Sada kada je svrha klauzule jasna, pogledajte sintaksu osnovnog grupiranog upita.
SELECT statements... GROUP BY column_name1[, column_name2, ...] [HAVING condition];
OVDJE
- "SELECT naredbe…"je standard" SQL SELECT upit naredbe.
- "GROUP BY naziv_stupca1" je klauzula koja izvršava grupuping na temelju naziva_stupca1.
- "[, naziv_stupca2, …]” je opcionalno i predstavlja nazive drugih stupaca kada je grupaping se vrši na više od jednog stupca.
- "[STANJE IMA]” je opcionalan i koristi se za ograničavanje redaka na koje utječe klauzula GROUP BY. Sličan je WHERE klauzula, osim što se nanosi nakon gruping.
Grouping Korištenje jednog stupca
Najbrži način da se vidi učinak SQL klauzule GROUP BY jest usporedba negrupiranog upita s grupiranim. Počnite s jednostavnim upitom koji vraća svaki unos spola u tablici članova.
SELECT `gender` FROM `members`;
| rod |
|---|
| ženski |
| ženski |
| Muški |
| ženski |
| Muški |
| Muški |
| Muški |
| Muški |
| Muški |
Vraća se devet redaka i svaka vrijednost se ponavlja. Pretpostavimo da umjesto toga želimo jedinstvene vrijednosti za spol. Upit u nastavku dodaje klauzulu GROUP BY.
SELECT `gender` FROM `members` GROUP BY `gender`;
Izvršavanje gornje skripte u MySQL Radna tezga u odnosu na myflixdb daje nam sljedeće rezultate.
| rod |
|---|
| ženski |
| Muški |
Imajte na umu da su vraćena samo dva retka jer tablica sadrži samo dva tipa spola. Klauzula GROUP BY grupirala je sve članove "Muški" i vratila jedan redak za njih, a isto je učinila i sa članovima "Ženski".
Grouping Korištenje više stupaca
Grouping na jednom stupcu je često pregrubo za pravo izvješće. GROUP BY prihvaća popis stupaca odvojen zarezima, a kombinacija njihovih vrijednosti definira svaku grupu.
Pretpostavimo da želimo popis vrijednosti category_id filma i odgovarajuće godine u kojima su filmovi objavljeni. Prvo promotrite izlaz ovog jednostavnog upita.
SELECT `category_id`, `year_released` FROM `movies`;
| kategorija_id | godina_izdana |
|---|---|
| 1 | 2011 |
| 2 | 2008 |
| NULL | 2008 |
| NULL | 2010 |
| 8 | 2007 |
| 6 | 2007 |
| 6 | 2007 |
| 8 | 2005 |
| NULL | 2012 |
| 7 | 1920 |
| 8 | NULL |
| 8 | 1920 |
Istaknuti retci pokazuju da rezultat sadrži duplikate. Izvršavanje istog upita s GROUP BY ih uklanja.
SELECT `category_id`, `year_released` FROM `movies` GROUP BY `category_id`, `year_released`;
Izvršavanje gornje skripte u MySQL Workbench u odnosu na myflixdb daje nam sljedeće rezultate prikazane u nastavku.
| kategorija_id | godina_izdana |
|---|---|
| NULL | 2008 |
| NULL | 2010 |
| NULL | 2012 |
| 1 | 2011 |
| 2 | 2008 |
| 6 | 2007 |
| 7 | 1920 |
| 8 | 1920 |
| 8 | 2005 |
| 8 | 2007 |
Klauzula GROUP BY djeluje i na category_id i na year_released kako bi identificirala jedinstveni retci. Dva duplicirana retka za kategoriju 6 u 2007. godini su se spojila u jedan.
Pravilo palca: Ako je ID kategorije isti, ali je godina izdavanja drugačija, redak se tretira kao jedinstven. Ako su ID kategorije i godina izdavanja isti za više redaka, retci su duplikati i prikazuje se samo jedan od njih.
Grouping i agregacijske funkcije
Uklanjanje duplikata je korisno, ali prava moć grupeping pojavljuje se kada je uparen s agregatne funkcijeAgregacijska funkcija izračunava jednu vrijednost za svaku grupu: COUNT broji retke, SUM zbraja vrijednosti i AVG, MIN i MAX opisuju raspršenost.
Pretpostavimo da želimo ukupan broj muških i ženskih članova u bazi podataka. Skript u nastavku to radi.
SELECT `gender`, COUNT(`membership_number`) FROM `members` GROUP BY `gender`;
Izvršavanje gornje skripte u MySQL Workbench na myflixdb daje nam sljedeće rezultate.
| rod | COUNT(`broj_članstva`) |
|---|---|
| ženski | 3 |
| Muški | 6 |
Redci su grupirani prema svakoj jedinstvenoj vrijednosti spola, a broj redaka unutar svake grupe broji se pomoću agregacijske funkcije COUNT. Devet zapisa članova sažima se u dva sažeta retka.
Ograničavanje rezultata upita pomoću klauzule HAVING
Groupingnisu uvijek poželjni za svaki redak u tablici. Ponekad izvješće mora biti ograničeno na zadani kriterij, a to je zadatak klauzule HAVING.
Pretpostavimo da želimo znati sve godine izlaska za filmsku kategoriju s ID-om 8. Skript u nastavku postiže taj rezultat.
SELECT * FROM `movies` GROUP BY `category_id`, `year_released` HAVING `category_id` = 8;
Izvršavanje gornje skripte u MySQL Workbench u odnosu na myflixdb daje nam sljedeće rezultate prikazane u nastavku.
| film_id | naslov | direktor | godina_izdana | kategorija_id |
|---|---|---|---|---|
| 9 | Honey moonERS | John Schultz | 2005 | 8 |
| 5 | Tatine djevojčice | NULL | 2007 | 8 |
Samo filmovi s ID-om kategorije 8 zadržani su uvjetom HAVING.
Upozorenje: MySQL Verzija 5.7 i novije omogućuju način rada ONLY_FULL_GROUP_BY prema zadanim postavkama, a u tom načinu rada SELECT * s klauzulom GROUP BY se odbija jer movie_id, title i director nisu ni grupirani ni agregirani. U produkciji, grupirane stupce eksplicitno imenujte, na primjer ODABERI category_id, year_leased FROM movies GROUP BY category_id, year_leased HAVING category_id = 8;
WHERE vs HAVING vs GROUP BY vs ORDER BY
Početnici često miješaju ove četiri klauzule jer sve one oblikuju skup rezultata. Razlika leži u kada MySQL primjenjuje ih: WHERE se izvršava prije grupiranja redaka, HAVING se izvršava nakon toga, a ORDER BY se izvršava posljednji od svih.
| Klauzula | Ono što se također | Kada se pokrene | Prihvaća agregacijske funkcije |
|---|---|---|---|
| GDJE | Filtrira pojedinačne retke prije bilo koje grupeping. | Prije GROUP BY | Ne |
| GROUP BY | Sažima retke koji dijele iste vrijednosti u jedan redak po grupi. | Nakon GDJE | Nije primjenjivo |
| IMAJUĆI | Filtrira grupe koje je proizvela naredba GROUP BY. | Nakon GRUPIRA PO | Da, na primjer HAVING COUNT(*) > 2 |
| NARUČITE PO | Sortira retke koji preživljavaju prethodne rečenice. | Prezime | Da, agregirani alias se može sortirati |
Praktična posljedica je posljedica performansi. Filtriranje s WHERE uklanja retke prije grupeping rad počinje, pa uvjet koji ne ovisi o agregiranom rezultatu pripada u WHERE, a ne u HAVING.
