🙏 Спасибо за поддержку! В июле собрали $65 — этого хватит ещё на месяц! Поддержите проект, чтобы сохранить темп. Поддержать проект →
SQL код скопирован в буфер обмена
EN PT FR

Урок 4.2 · Время чтения: ~7 минут

Группировка данных позволяет превратить набор отдельных строк в категоризованные метрики. GROUP BY — ключевой оператор для отчетов, где нужны итоги по категориям, дням или любым другим признакам. В этом уроке вы разберете синтаксис GROUP BY, главное правило и практические примеры на Sakila. К концу урока вы сможете уверенно строить аналитические запросы с группировкой.

Группировка данных с помощью GROUP BY

В предыдущем уроке вы узнали об агрегатных функциях. Теперь идем дальше: как применять эти функции к разным категориям данных.

GROUP BY решает эту задачу, позволяя разбить данные на группы и считать метрики для каждой группы отдельно.

Синтаксис GROUP BY

Базовая структура:

SELECT column1, AGG_FUNCTION(column2)
FROM table
GROUP BY column1;

Главное правило

Когда используете GROUP BY, каждый столбец в SELECT должен:

  • либо быть в списке GROUP BY;
  • либо быть обёрнут в агрегатную функцию (SUM, COUNT, AVG, MIN, MAX).

Это правило помогает избежать неоднозначности: SQL должен знать, какое значение вернуть для столбца, если в группе несколько строк.

Группировка по одному столбцу

Сумма платежей по каждому клиенту

SELECT customer_id, SUM(amount) AS total_paid
FROM payment
GROUP BY customer_id;

Результат: для каждого клиента одна строка с суммой его платежей.

Количество платежей по сотруднику

SELECT staff_id, COUNT(*) AS payments_count
FROM payment
GROUP BY staff_id;

Результат: для каждого сотрудника показано, сколько платежей он обработал.

Средний платеж по дате

SELECT DATE(payment_date) AS pay_date, AVG(amount) AS avg_payment
FROM payment
GROUP BY DATE(payment_date);

Результат: для каждой даты выводится средний размер платежа.

Вариант: GROUP BY с алиасом

SELECT DATE(payment_date) AS pay_date, AVG(amount) AS avg_payment
FROM payment
GROUP BY pay_date;

Примечание: этот вариант работает в MySQL/MariaDB, но не во всех СУБД. Для кросс-СУБД совместимости лучше писать GROUP BY DATE(payment_date) полностью.


Группировка по нескольким столбцам

Можно группировать по нескольким полям одновременно для более детального анализа.

Сумма платежей по сотруднику и клиенту

SELECT staff_id, customer_id, SUM(amount) AS total_paid
FROM payment
GROUP BY staff_id, customer_id;

Результат: для каждой пары (сотрудник, клиент) выводится сумма платежей.


Практические примеры

Отчет по выручке за каждый день

SELECT DATE(payment_date) AS pay_date, SUM(amount) AS total_sales
FROM payment
GROUP BY DATE(payment_date)
ORDER BY pay_date;

Самые активные клиенты по числу аренд

SELECT customer_id, COUNT(*) AS rentals_count
FROM rental
GROUP BY customer_id
ORDER BY rentals_count DESC;

Среднее количество фильмов по категориям

SELECT category_id, AVG(rental_rate) AS avg_rental_rate
FROM film f
JOIN film_category fc ON f.film_id = fc.film_id
GROUP BY category_id;

Часто задаваемые вопросы

Почему не все столбцы SELECT должны быть в GROUP BY?

Потому что агрегатные функции (SUM, COUNT, AVG) уже указывают, как обработать остальные строки группы. Если столбец не агрегирован, он должен быть в GROUP BY, иначе неясно, какое его значение выбрать.

Можно ли группировать по выражению, а не по столбцу?

Да, например GROUP BY DATE(payment_date) или GROUP BY YEAR(payment_date). Главное — выражение должно быть одинаковым в SELECT и GROUP BY.

Что будет, если GROUP BY пуст?

Это синтаксическая ошибка. GROUP BY всегда должен иметь хотя бы один столбец или выражение.


Вопросы для собеседования

Что такое GROUP BY и зачем оно нужно?

GROUP BY объединяет строки, где выбранные столбцы имеют одинаковые значения, в одну группу. К каждой группе можно применить агрегатные функции для получения сводных показателей.

Почему нельзя выбрать произвольный столбец, если используется GROUP BY?

Потому что в одной группе может быть несколько строк с разными значениями. SQL должен знать, какое значение вернуть для этого столбца, иначе результат неоднозначен. Поэтому столбец либо в GROUP BY, либо в функции.

Какая разница между WHERE и HAVING?

WHERE фильтрует строки ДО группировки, а HAVING фильтрует группы ПОСЛЕ группировки. Например, WHERE amount > 10 исключит строки до группировки, а HAVING SUM(amount) > 100 исключит группы с суммой менее 100.


Ключевые выводы этого урока:

  • GROUP BY позволяет разбить данные на группы и применить агрегаты к каждой.
  • Главное правило: все столбцы в SELECT либо в GROUP BY, либо в агрегатной функции.
  • Можно группировать по одному или нескольким столбцам одновременно.
  • Можно группировать по выражениям, например GROUP BY DATE(payment_date).
  • GROUP BY используется для отчетов, аналитики и получения итогов по категориям.

В следующем уроке мы разберем фильтрацию групп с помощью оператора HAVING.

Попробуйте решить следующие задачи, чтобы закрепить материал этого урока.

  1. Среднее время проката фильма клиентом
  2. Средняя стоимость проката фильма по категории
  3. Анализ ежемесячных платежей
  4. Средняя выручка по пунктам аренды
  5. Количество фильмов в каждой категории