GROUP BY и HAVING - группировка данных
Операторы GROUP BY
группирует строки с одинаковыми значениями в сводные строки. Часто используется с агрегатными функциями COUNT
, MAX
, MIN
, SUM
, AVG
для группировки результирующего набора по одному или нескольким столбцам.
Команда HAVING
по значениям агрегатных функций, позволяет фильтровать результат группировки, сделанной с помощью команды GROUP BY
.
Оба оператора употребляются в рамках команды SELECT
:
SELECT `столбцы`
FROM `список_столбцов` WHERE `условие_фильтрации_строк`
[GROUP BY `столбцы_для_группировки`]
[HAVING `условие_фильтрации_групп`]
[ORDER BY с`толбцы_для_сортировки`];
Базы данных:
CREATE DATABASE IF NOT EXISTS productsdb;
USE productsdb;
CREATE TABLE Products
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
ProductCount INT DEFAULT 0,
Price DECIMAL NOT NULL
);
Заполнение баз данных:
USE productsdb;
INSERT INTO Products (ProductName, Manufacturer, ProductCount, Price) VALUES
('iPhone X', 'Apple', 3, 71000),
('iPhone 8', 'Apple', 3, 56000),
('Galaxy S9', 'Samsung', 6, 56000),
('Galaxy S8', 'Samsung', 2, 46000),
('Honor 10', 'Huawei', 3, 26000);
GROUP BY
Оператор GROUP BY
определяет, как строки будут группироваться. Например, сгруппируем товары по производителю:
SELECT `Manufacturer`, COUNT(*) AS `ModelsCount`
FROM `Products`
GROUP BY `Manufacturer`;
Первый столбец в выражении SELECT Manufacturer
- представляет название группы, а второй столбец - ModelsCount
представляет результат функции Count
, которая вычисляет количество строк в группе.
И если в выражении SELECT
производится выборка по одному или нескольким столбцам и также используются агрегатные
функции, то необходимо использовать выражение GROUP BY
. Так, следующий пример работать не будет, так как он не
содержит выражение группировки:
SELECT `Manufacturer`, COUNT(*) AS `ModelsCount`
FROM `Products`;
Оператор GROUP BY
может выполнять группировку по множеству столбцов. Так, добавим группировку по
количеству товаров:
SELECT `Manufacturer`, `ProductCount`, COUNT(*) AS `ModelsCount`
FROM `Products`
GROUP BY `Manufacturer`, `ProductCount`;
Следует учитывать, что выражение GROUP BY
должно идти после выражения WHERE
, но до
выражения ORDER BY
:
SELECT `Manufacturer`, COUNT(*) AS `ModelsCount`
FROM `Products`
WHERE `Price`>30000
GROUP BY `Manufacturer`
ORDER BY `ModelsCount` DESC;
HAVING фильтрация групп
Оператор HAVING
по значениям агрегатных функций позволяет выполнить фильтрацию групп, определяет какие группы будут
включены в выходной результат.
Использование HAVING
во многом аналогично применению WHERE
. Только если WHERE
применяется для фильтрации строк, то
HAVING
- для фильтрации групп.
Например, найдем все группы товаров по производителям, для которых определено более 1 модели:
SELECT `Manufacturer`, COUNT(*) AS `ModelsCount`
FROM `Products`
GROUP BY `Manufacturer`
HAVING COUNT(*)>1;
В одной команде также можно сочетать выражения WHERE
и HAVING
:
SELECT `Manufacturer`, COUNT(*) AS `ModelsCount`
FROM `Products`
WHERE `Price`*`ProductCount`>80000
GROUP BY `Manufacturer`
HAVING COUNT(*)>1;
То есть в данном случае сначала фильтруются строки: выбираются те товары, общая стоимость которых больше 80000. Затем выбранные товары группируются по производителям. И далее фильтруются сами группы - выбираются те группы, которые содержат больше 1 модели.
Если при этом необходимо провести сортировку, то выражение ORDER BY
идет после выражения HAVING
:
SELECT `Manufacturer`, COUNT(*) AS `Models`, SUM(ProductCount) AS Units
FROM `Products`
WHERE `Price`*`ProductCount`>80000
GROUP BY `Manufacturer`
HAVING SUM(ProductCount)>2
ORDER BY Units DESC;
Здесь группировка идет по производителям, и также выбирается количество моделей для каждого производителя Models
и общее количество всех товаров по всем этим моделям Units
. В конце группы сортируются по количеству товаров по
убыванию.