Операторы GROUP BY и HAVING позволяют сгруппировать данные. Они употребляются в рамках команды SELECT:
| 1 2 3 4 5 6 | SELECT столбцыFROM таблица[WHERE условие_фильтрации_строк][GROUP BY столбцы_для_группировки][HAVING условие_фильтрации_групп][ORDER BY столбцы_для_сортировки] |
GROUP BY
Оператор GROUP BY определяет, как строки будут группироваться.
Например, сгруппируем товары по производителю
| 1 2 3 | SELECT Manufacturer, COUNT(*) AS ModelsCountFROM ProductsGROUP BY Manufacturer |
Первый столбец в выражении SELECT — Manufacturer представляет название группы, а второй столбец — ModelsCount представляет результат функции Count, которая вычисляет количество строк в группе.

И если в выражении SELECT производится выборка по одному или нескольким столбцам и также используются агрегатные функции, то необходимо использовать выражение GROUP BY. Так, следующий пример работать не будет, так как он не содержит выражение группировки:
| 1 2 | SELECT Manufacturer, COUNT(*) AS ModelsCountFROM Products |
Оператор GROUP BY может выполнять группировку по множеству столбцов. Так, добавим группировку по количеству товаров:
| 1 2 3 | SELECT Manufacturer, ProductCount, COUNT(*) AS ModelsCountFROM ProductsGROUP BY Manufacturer, ProductCount |
Следует учитывать, что выражение GROUP BY должно идти после выражения WHERE, но до выражения ORDER BY:
| 1 2 3 4 5 | SELECT Manufacturer, COUNT(*) AS ModelsCountFROM ProductsWHERE Price > 30000GROUP BY ManufacturerORDER BY ModelsCount DESC |

Фильтрация групп. HAVING
Оператор HAVING позволяет выполнить фильтрацию групп, то есть определяет, какие группы будут включены в выходной результат.
Использование HAVING во многом аналогично применению WHERE. Только есть WHERE применяется для фильтрации строк, то HAVING — для фильтрации групп.
Например, найдем все группы товаров по производителям, для которых определено более 1 модели:
| 1 2 3 4 | SELECT Manufacturer, COUNT(*) AS ModelsCountFROM ProductsGROUP BY ManufacturerHAVING COUNT(*) > 1 |

В одной команде также можно сочетать выражения WHERE и HAVING:
| 1 2 3 4 5 | SELECT Manufacturer, COUNT(*) AS ModelsCountFROM ProductsWHERE Price * ProductCount > 80000GROUP BY ManufacturerHAVING COUNT(*) > 1; |
То есть в данном случае сначала фильтруются строки: выбираются те товары, общая стоимость которых больше 80000. Затем выбранные товары группируются по производителям. И далее фильтруются сами группы — выбираются те группы, которые содержат больше 1 модели.
Если при этом необходимо провести сортировку, то выражение ORDER BY идет после выражения HAVING:
| 1 2 3 4 5 6 | SELECT Manufacturer, COUNT(*) AS Models, SUM(ProductCount) AS UnitsFROM ProductsWHERE Price * ProductCount > 80000GROUP BY ManufacturerHAVING SUM(ProductCount) > 2ORDER BY Units DESC; |
Здесь группировка идет по производителям, и также выбирается количество моделей для каждого производителя (Models) и общее количество всех товаров по всем этим моделям (Units). В конце группы сортируются по количеству товаров по убыванию.
