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 на основе column_name1.
- [, column_name2, …]"" — необязательный параметр, который обозначает другие имена столбцов при группировке.ping выполняется более чем в одном столбце.
- [Имеющий заболевание]Параметр ” является необязательным и используется для ограничения строк, на которые распространяется действие предложения GROUP BY. Он аналогичен параметру ” Предложение WHEREза исключением того, что оно применяется после группыping.
Grouping Использование одного столбца
Самый быстрый способ увидеть эффект от предложения SQL GROUP BY — сравнить запрос без группировки с запросом с группировкой. Начнём с простого запроса, который возвращает все записи о поле в таблице members.
SELECT `gender` FROM `members`;
| пол |
|---|
| F |
| F |
| M |
| F |
| M |
| M |
| M |
| M |
| M |
Возвращается девять строк, и каждое значение повторяется. Предположим, нам нужны уникальные значения для пола. В приведенном ниже запросе добавлено предложение GROUP BY.
SELECT `gender` FROM `members` GROUP BY `gender`;
Выполнение приведенного выше сценария в MySQL Верстак против myflixdb дает нам следующие результаты.
| пол |
|---|
| F |
| M |
Обратите внимание, что было возвращено только две строки, поскольку таблица содержит только два типа пола. Предложение GROUP BY сгруппировало всех членов с пометкой «Мужской» и вернуло для них одну строку, то же самое было сделано и с членами с пометкой «Женский».
Grouping Использование нескольких столбцов
Grouping Значения в одном столбце часто слишком грубы для полноценного отчета. Функция GROUP BY принимает список столбцов, разделенных запятыми, а комбинация их значений определяет каждую группу.
Предположим, нам нужен список значений category_id для фильмов и соответствующих годов их выпуска. Сначала взгляните на результат этого простого запроса.
SELECT `category_id`, `year_released` FROM `movies`;
| ид_категории | год_выпущено |
|---|---|
| 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, показаны ниже.
| ид_категории | год_выпущено |
|---|---|
| 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(`membership_number`) |
|---|---|
| F | 3 |
| M | 6 |
Строки сгруппированы по каждому уникальному значению пола, а количество строк внутри каждой группы подсчитывается с помощью агрегатной функции COUNT. Девять записей участников объединяются в две сводные строки.
Ограничение результатов запроса с помощью предложения HAVING
GroupingНе всегда требуется указывать значение для каждой строки в таблице. Иногда отчет должен быть ограничен определенным критерием, и именно для этого предназначено предложение HAVING.
Предположим, нам нужно узнать все годы выпуска фильмов с идентификатором категории 8. Приведенный ниже скрипт позволяет получить этот результат.
SELECT * FROM `movies` GROUP BY `category_id`, `year_released` HAVING `category_id` = 8;
Выполнение приведенного выше сценария в MySQL Результаты, полученные с помощью Workbench при работе с базой данных myflixdb, показаны ниже.
| Movie_id | название | директор | год_выпущено | ид_категории |
|---|---|---|---|---|
| 9 | Honey moonERS | Джон Шульц | 2005 | 8 |
| 5 | Папины маленькие девочки | NULL, | 2007 | 8 |
В соответствии с условием HAVING были сохранены только фильмы с идентификатором категории 8.
Внимание! MySQL В версиях 5.7 и более поздних по умолчанию включен режим ONLY_FULL_GROUP_BY, и в этом режиме запрос SELECT * с предложением GROUP BY отклоняется, поскольку movie_id, title и director не группируются и не агрегируются. В рабочей среде указывайте имена сгруппированных столбцов явно, например: SELECT category_id, year_released FROM movies GROUP BY category_id, year_released HAVING category_id = 8;
WHERE vs HAVING vs GROUP BY vs ORDER BY
Начинающие часто путают эти четыре пункта, поскольку все они влияют на результирующий набор данных. Разница заключается в следующем: когда MySQL Применяется следующий алгоритм: WHERE выполняется до группировки строк, HAVING — после, а ORDER BY — в последнюю очередь.
| пункт | Что она делает | Когда он работает | Принимает агрегатные функции |
|---|---|---|---|
| ГДЕ | Фильтрует отдельные строки перед группировкой.ping. | Перед группировкой по | Нет |
| ГРУППА ПО | Объединяет строки с одинаковыми значениями в одну строку для каждой группы. | После ГДЕ | Непригодный |
| HAVING | Фильтрует группы, созданные функцией GROUP BY. | После GROUP BY | Да, например, HAVING COUNT(*) > 2 |
| СОРТИРОВАТЬ ПО | Сортирует строки, которые остались после выполнения предыдущих условий. | Фамилия | Да, агрегированный псевдоним можно отсортировать. |
Практическим следствием является снижение производительности. Фильтрация с помощью WHERE удаляет строки до заданного диапазона.ping Работа начинается, поэтому условие, не зависящее от агрегированного результата, следует использовать в операторе WHERE, а не в операторе HAVING.
