SUM, AVG, MIN и MAX в SQL: агрегатные функции на рабочих примерах
Как применять SUM, AVG, MIN и MAX в SQL для выручки, среднего чека, первой и последней активности, не ломая зерно и знаменатель.
Содержание статьи
SUM, AVG, MIN и MAX выглядят элементарно, но ошибка в уровне агрегации быстро портит отчёт. Среднее по заказам не равно среднему по пользователям, MIN по таблице не показывает первую активность каждого клиента, а SUM после размножающего JOIN может удвоить выручку. Разберём вопрос на одном запросе: Как выбрать агрегатную функцию, чтобы результат отвечал на бизнес-вопрос?
Сначала определим задачу
Как выбрать агрегатную функцию, чтобы результат отвечал на бизнес-вопрос?
Если нужно узнать средний чек, AVG(amount) по заказам отвечает на один вопрос. Если нужен средний доход на покупателя, сначала собери сумму по user_id, затем усредни пользователей. Для первой покупки используй MIN(paid_at) по user_id, а не MIN(paid_at) по всей таблице.
Агрегат выбирается не по привычке, а по объекту измерения. Для финансового итога нужен SUM, для среднего уровня — AVG с явным знаменателем, для жизненного цикла — MIN/MAX. Если запрос содержит JOIN, сначала проверь зерно обеих сторон.
Как работает конструкция
Агрегатная функция сжимает несколько строк в одно значение внутри группы. Поэтому до написания функции нужно определить единицу результата и набор строк, которые попадут в группу. NULL обычно игнорируется агрегатами, что может быть правильным или скрывать неполные данные — это нужно проверять отдельно.
Запиши формулу словами и укажи знаменатель. Проверь итоговую сумму с независимой сверкой. Сравни COUNT(*) и COUNT(column), если есть NULL. Для min/max по времени добавь фильтр на валидные даты и подумай, что означает «нет события».
- Зафиксируй одну строку результата.
- Отдели условия по исходным строкам от условий по рассчитанным значениям.
- Назови период, ключи связи и правило для повторов.
Запрос по шагам
Названия таблиц здесь условные. При переносе сохрани зерно и бизнес-условия, а не буквальный синтаксис примера.
SELECT user_id, SUM(amount) AS user_revenue, AVG(amount) AS avg_order_value,
MIN(paid_at) AS first_order_at, MAX(paid_at) AS last_order_at
FROM orders
WHERE status = 'paid'
GROUP BY user_id;Проверка результата
Собери пять-десять строк, где ответ можно получить вручную. Добавь NULL, дубль, объект без связанной записи и значение на границе периода. Затем сравни число строк и уникальных ключей до и после спорного шага.
Выполненный без ошибки запрос ещё не является правильным. Другой аналитик должен суметь восстановить из него источник, фильтр, grain и ожидаемое поведение на крайних случаях.
| Функция | Вопрос | Риск |
|---|---|---|
| SUM | каков общий объём? | дубли после JOIN |
| AVG | каково среднее наблюдение? | неверный знаменатель |
| MIN | какое первое значение? | невалидные даты |
| MAX | какое последнее значение? | тестовая запись |
Границы и альтернативы
AVG не показывает типичного пользователя при длинном хвосте. SUM после JOIN one-to-many нужно считать до соединения или на корректном зерне. MIN/MAX не диагностируют выбросы. COUNT(column) не считает NULL, а COUNT(*) считает строки.
Агрегат выбирается не по привычке, а по объекту измерения. Для финансового итога нужен SUM, для среднего уровня — AVG с явным знаменателем, для жизненного цикла — MIN/MAX. Если запрос содержит JOIN, сначала проверь зерно обеих сторон.
Агрегаты отвечают на разные вопросы и не заменяют друг друга.
Задание для самостоятельной проверки
Сделай витрину с четырьмя показателями по каналу: orders, revenue, average order value и first/last order date. Затем добавь пользователя с двумя заказами и вручную проверь, что средний чек и средний доход на пользователя не смешались.
- Сначала запиши ожидаемый результат словами.
- Проверь запрос на маленькой контрольной выборке.
- Объясни, что запрос считает и чего не доказывает.
Решение для команды
Агрегат выбирается не по привычке, а по объекту измерения. Для финансового итога нужен SUM, для среднего уровня — AVG с явным знаменателем, для жизненного цикла — MIN/MAX. Если запрос содержит JOIN, сначала проверь зерно обеих сторон.
Материалы по теме
Собеседование аналитика данных: 30 задач и как решать их вслух
Большой практический гайд по собеседованию аналитика данных: SQL, Python, метрики, статистика, кейсы, дашборды и ответы, которые показывают ход мышления.
Порядок выполнения SQL-запроса: почему WHERE не видит alias из SELECT
Разбираем логический порядок выполнения SQL-запроса: FROM, WHERE, GROUP BY, HAVING, SELECT и ORDER BY. Примеры помогают понять ошибки alias и агрегации.
ORDER BY, LIMIT и OFFSET в SQL: сортировка и пагинация без ошибок
Как сортировать данные в SQL, выбирать top-N, строить стабильную пагинацию и не терять строки при одинаковых значениях.