MySQL GROUP BY и HAVING Клауза с примери
⚡ Умно обобщение
Клаузите SQL GROUP BY и HAVING превръщат подробните редове в обобщени отчети. GROUP BY свива редовете, които споделят едни и същи стойности, в един ред на група, докато HAVING филтрира тези групи, след като са приложени агрегиращи функции, като например COUNT.

Какво представлява SQL клаузата GROUP BY?
Клаузата GROUP BY е SQL команда, която се използва за групирайте редове, които имат еднакви стойностиНаписва се в рамките на оператора SELECT и обикновено се използва заедно с агрегатни функции за генериране на обобщени отчети от базата данни.
Това прави то: обобщава данни съхранявани в базата данни. Заявките, които съдържат клаузата GROUP BY, се наричат групирани заявки и те връщат по един ред за всеки групиран елемент.
SQL ГРУПИРАНЕ ПО Синтаксис
След като целта на клаузата е ясна, разгледайте синтаксиса на основна групирана заявка.
SELECT statements... GROUP BY column_name1[, column_name2, ...] [HAVING condition];
ТУК
- "SELECT оператори…„е стандартът“ SQL SELECT командна заявка.
- "ГРУПИРАЙ ПО име_на_колона1„е клаузата, която изпълнява групата“ping въз основа на име_на_колона1.
- "[, име_на_колона2, …]„“ е по избор и представлява други имена на колони, когато групатаping се извършва на повече от една колона.
- "[НАЛИЧНО състояние]„“ е по избор и се използва за ограничаване на редовете, засегнати от клаузата GROUP BY. Подобно е на WHERE клауза, с изключение на това, че се прилага след групатаping.
Grouping Използване на една колона
Най-бързият начин да видите ефекта от SQL клаузата GROUP BY е да сравните негрупирана заявка с групирана. Започнете с проста заявка, която връща всеки запис за пол в таблицата „members“.
SELECT `gender` FROM `members`;
| пол |
|---|
| Женски |
| Женски |
| Мъжки |
| Женски |
| Мъжки |
| Мъжки |
| Мъжки |
| Мъжки |
| Мъжки |
Връщат се девет реда и всяка стойност се повтаря. Да предположим, че вместо това искаме уникалните стойности за пол. Заявката по-долу добавя клаузата GROUP BY.
SELECT `gender` FROM `members` GROUP BY `gender`;
Изпълнение на горния скрипт в MySQL Workbench срещу myflixdb ни дава следните резултати.
| пол |
|---|
| Женски |
| Мъжки |
Обърнете внимание, че са върнати само два реда, защото таблицата съдържа само два типа пол. Клаузата GROUP BY групира всички членове „Мъжки“ заедно и връща един ред за тях, като същото прави и с членовете „Женски“.
Grouping Използване на множество колони
Grouping в една колона често е твърде грубо за истински отчет. GROUP BY приема списък от колони, разделени със запетаи, и комбинацията от техните стойности определя всяка група.
Да предположим, че искаме списък със стойности на category_id на филма и съответните години, в които са пуснати филмите. Първо разгледайте резултата от тази проста заявка.
SELECT `category_id`, `year_released` FROM `movies`;
| категория_id | year_released |
|---|---|
| 1 | 2011 |
| 2 | 2008 |
| NULL | 2008 |
| NULL | 2010 |
| 8 | 2007 |
| 6 | 2007 |
| 6 | 2007 |
| 8 | 2005 |
| NULL | 2012 |
| 7 | 1920 |
| 8 | NULL |
| 8 | 1920 |
Маркираните редове показват, че резултатът съдържа дубликати. Изпълнението на същата заявка с GROUP BY ги премахва.
SELECT `category_id`, `year_released` FROM `movies` GROUP BY `category_id`, `year_released`;
Изпълнение на горния скрипт в MySQL Workbench срещу myflixdb ни дава следните резултати, показани по-долу.
| категория_id | year_released |
|---|---|
| NULL | 2008 |
| NULL | 2010 |
| NULL | 2012 |
| 1 | 2011 |
| 2 | 2008 |
| 6 | 2007 |
| 7 | 1920 |
| 8 | 1920 |
| 8 | 2005 |
| 8 | 2007 |
Клаузата GROUP BY работи както с category_id, така и с year_released, за да идентифицира уникален редове. Двата дублиращи се реда за категория 6 през 2007 г. се сляха в един.
Правило на палеца: Ако идентификаторът на категорията е един и същ, но годината на издаване е различна, редът се третира като уникален. Ако идентификаторът на категорията и годината на издаване са еднакви за повече от един ред, редовете са дубликати и се показва само един от тях.
Grouping и агрегиращи функции
Премахването на дубликати е полезно, но истинската сила на групата...ping се появява, когато е сдвоен с агрегатни функцииАгрегатната функция изчислява по една стойност за всяка група: COUNT брои редове, SUM сумира стойности и AVG, MIN и MAX описват разпространението.
Да предположим, че искаме общия брой мъже и жени в базата данни. Скриптът по-долу прави това.
SELECT `gender`, COUNT(`membership_number`) FROM `members` GROUP BY `gender`;
Изпълнение на горния скрипт в MySQL Workbench срещу myflixdb ни дава следните резултати.
| пол | COUNT(`номер_на_членство`) |
|---|---|
| Женски | 3 |
| Мъжки | 6 |
Редовете са групирани по всяка уникална стойност за пол, а броят на редовете във всяка група се преброява от агрегатната функция COUNT. Деветте записа на членовете се свиват в два обобщени реда.
Ограничаване на резултатите от заявките с помощта на клаузата HAVING
GroupingНе винаги са желателни за всеки ред в таблицата. Понякога отчетът трябва да бъде ограничен до даден критерий и това е задачата на клаузата HAVING.
Да предположим, че искаме да знаем всички години на издаване за филм с идентификатор на категория 8. Скриптът по-долу постига този резултат.
SELECT * FROM `movies` GROUP BY `category_id`, `year_released` HAVING `category_id` = 8;
Изпълнение на горния скрипт в MySQL Workbench срещу myflixdb ни дава следните резултати, показани по-долу.
| movie_id | заглавие | директор | year_released | категория_id |
|---|---|---|---|---|
| 9 | Honey moonERS | Джон Шулц | 2005 | 8 |
| 5 | Малките момичета на татко | NULL | 2007 | 8 |
Само филмите с идентификатор на категория 8 са запазени чрез условието HAVING.
Внимание: MySQL 5.7 и по-нови версии активират режима ONLY_FULL_GROUP_BY по подразбиране и в този режим SELECT * с клауза GROUP BY се отхвърля, защото movie_id, title и director не са нито групирани, нито агрегирани. В продукция, наименувайте групираните колони изрично, например ИЗБЕРЕТЕ category_id, year_released ОТ филми GROUP BY category_id, year_released HAVING category_id = 8;
WHERE срещу HAVING срещу GROUP BY срещу ORDER BY
Начинаещите често смесват тези четири клаузи, защото всички те оформят резултатния набор. Разликата се състои в когато MySQL прилага ги: WHERE се изпълнява преди групирането на редовете, HAVING се изпълнява след това, а ORDER BY се изпълнява последен от всички.
| Клауза | Какво го прави | Когато работи | Приема агрегатни функции |
|---|---|---|---|
| КЪДЕ | Филтрира отделни редове преди всяка групаping. | Преди GROUP BY | Не |
| ГРУПИРАЙ ПО | Свива редове, споделящи едни и същи стойности, в един ред на група. | След КЪДЕ | Не е приложимо |
| КАТО | Филтрира групите, получени от GROUP BY. | След ГРУПИРАНЕ ПО | Да, например HAVING COUNT(*) > 2 |
| ПОДРЕДЕНИ ПО | Сортира редовете, които оцеляват след предишните клаузи. | Фамилно | Да, агрегиран псевдоним може да бъде сортиран |
Практическото следствие е свързано с производителността. Филтрирането с WHERE премахва редове преди групата.ping работата започва, така че условие, което не зависи от агрегиран резултат, принадлежи към WHERE, а не към HAVING.
