Агрегатные функции и GROUP BY
Считаем итоги: агрегатные функции
До сих пор каждый запрос возвращал строки «как есть». Но часто нужны не сами строки, а итог по ним: «сколько всего самолётов», «средняя скорость», «самый дальнобойный». Для этого есть агрегатные функции — они сворачивают много строк в одно значение:
| Функция | Что считает |
|---|---|
COUNT(*) | количество строк |
SUM(x) | сумму значений столбца x |
AVG(x) | среднее |
MIN(x) / MAX(x) | минимум / максимум |
SELECT COUNT(*) AS cnt
FROM airplanes; -- сколько всего самолётов → 10
Можно посчитать сразу несколько итогов в одном запросе, и каждому удобно дать псевдоним через AS:
SELECT AVG(speed) AS avg_speed,
MIN(speed) AS min_speed,
MAX(speed) AS max_speed
FROM airplanes;
Дробное среднее удобно округлять функцией ROUND(значение, знаков): ROUND(AVG(speed), 1) — до одного знака после запятой.
⚠️ Агрегаты и NULL:COUNT(*)считает все строки, аCOUNT(x),SUM(x),AVG(x),MIN(x)иMAX(x)пропускают строки, гдеx IS NULL. ПоэтомуCOUNT(*)иCOUNT(x)могут вернуть разные числа.
GROUP BY — итоги по группам
Самое интересное начинается, когда нужно посчитать итог отдельно для каждой группы: сколько мест каждого класса, сколько рейсов в каждом статусе, сколько аэропортов в каждой стране. Здесь помогает GROUP BY: он разбивает строки на группы по значению столбца, и агрегат считается внутри каждой группы.
SELECT fare_conditions, COUNT(*) AS cnt
FROM seats
GROUP BY fare_conditions;
Этот запрос вернёт по одной строке на каждый класс обслуживания и количество мест в нём.
Разбор: как база выполняет GROUP BY
Возьмём запрос SELECT fare_conditions, COUNT(*) AS cnt FROM seats GROUP BY fare_conditions и пройдём его по шагам:
FROM seats— база берёт все места всех самолётов.GROUP BY fare_conditions— раскладывает их на «кучки»: Economy, Comfort, Business.COUNT(*)— в каждой кучке считает строки.SELECT— для каждой кучки выводит одну строку: название класса и число мест.
Отсюда и золотое правило: после группировки у каждой кучки есть одно общее значение fare_conditions, но много разных seat_no. Поэтому seat_no можно вывести только внутри агрегата — например, MIN(seat_no).
Типичные ошибки
- Столбец не в GROUP BY.
SELECT model, COUNT(*) FROM airplanes— ошибка: непонятно, какую модель показать рядом с общим числом. - Агрегат в WHERE.
WHERE COUNT(*) > 5— ошибка:WHEREработает до подсчёта. Для условий на агрегаты естьHAVING— о нём следующий урок. - COUNT(*) и COUNT(столбец). Первый считает все строки, второй — только строки, где столбец заполнен. На столбцах с пустыми значениями они дают разные числа.
⚠️ Золотое правило GROUP BY: каждый столбец вSELECT, который НЕ обёрнут в агрегатную функцию, обязан присутствовать вGROUP BY. Иначе база не поймёт, какое из значений группы показать, и выдаст ошибку.
Результат группировки тоже можно сортировать. Частый приём — «от самой большой группы к маленькой»: ORDER BY cnt DESC (можно сортировать прямо по псевдониму агрегата).
Практика
9- Тест 1 — Почему запрос «SELECT model, COUNT(*) FROM airplanes;» завершится ошибкой?
- Тест 2 — Чем COUNT(*) отличается от COUNT(actual_departure)?
- Задача 1 — Сколько всего самолётов
- Задача 2 — Средний и максимальный чек
- Задача 3 — Сколько разных стран (COUNT DISTINCT)
- Задача 4 — Места по классам обслуживания
- Задача 5 — Рейсы по статусам
- Задача 6 — Перелёты и выручка по классам
- Задача 7 — Аэропорты с наибольшим числом маршрутов прилёта
Задачи решаются прямо здесь, в браузере, на учебной базе — нужна только бесплатная регистрация, чтобы сохранялись ответы и прогресс.
Потренируйтесь в тренажёре
16Задачи на ту же тему, но на другой базе — продажи магазина электроники. Хороший способ проверить, что тема понятна, а не просто запомнилась на примерах урока.
- лёгкаяКоличество устройств по типам
- лёгкаяСредняя цена устройства
- лёгкаяСколько уникальных брендов
- лёгкаяПокупатели по уровню лояльности
- лёгкаяУстройства по ОС