- -
- 100%
- +

Перед первым отчётом
Зачем отдельная книга про группировки
GROUP BY выглядит простым, пока отчёт не начинает отвечать на неправильный вопрос. Одна лишняя колонка, забытый фильтр или неверный уровень группировки меняют смысл результата.
Эта книга идёт от базовых агрегатов к отчётным конструкциям: HAVING, CASE, COUNT DISTINCT, подзапросы, CTE и объединение со справочниками.
Мы используем маленькие искусственные таблицы магазина, чтобы каждая задача проверялась глазами и запускалась локально без внешней базы.
Как работать с примерами
Перед запуском запроса назовите единицу результата: строка на статус, категория, месяц, клиент, пара месяц-канал или весь отчёт. Это защищает от случайной группировки.
После результата проверьте не только числа, но и количество строк. В отчётах ошибка часто прячется именно там: строк стало больше или меньше, чем ожидалось.
Все запросы написаны под SQLite. В PostgreSQL, MySQL или ClickHouse могут отличаться функции дат, но сама логика группировки останется той же.
Маршрут по задачам
1. Посчитать заказы по статусам
2. Сложить выручку по категориям
3. Найти средний чек клиента
4. Оставить группы через HAVING
5. Собрать выручку по месяцам
6. Посчитать уникальных клиентов
7. Показать минимум и максимум
8. Сгруппировать через CASE
9. Не потерять пустую категорию
10. Сделать ценовые корзины
11. Вывести одну лучшую группу
12. Посчитать долю от общей суммы
13. Найти дубли по email
14. Взвешенное среднее
15. Группировка по двум измерениям
16. Добавить итоговую строку
17. Схлопнуть грязные категории
18. Итоговый отчёт по товарам
Восемнадцать задач
Задача 1. Посчитать заказы по статусам
Рабочий вопросНужно понять, сколько заказов находится в каждом статусе, чтобы увидеть баланс между новыми, оплаченными и отменёнными строками.
ДанныеCREATE TABLE orders(id INTEGER, status TEXT);
INSERT INTO orders VALUES
(1,'paid'),(2,'new'),(3,'paid'),(4,'cancelled'),(5,'new'),(6,'paid');
ЗапросSELECT status, COUNT(*) AS orders_count
FROM orders
GROUP BY status
ORDER BY status;
Ожидаемый результат[["cancelled", 1], ["new", 2], ["paid", 3]]
Почему работаетGROUP BY status собирает строки с одинаковым статусом в одну группу.
COUNT(*) считает все строки внутри каждой группы.
ORDER BY нужен не для расчёта, а для стабильного порядка отчёта.
Где легко ошибитьсяЕсли убрать GROUP BY, COUNT(*) вернёт одну строку по всей таблице, а не разрез по статусам.
Самостоятельная проверкаДобавьте ещё один paid-заказ и проверьте, что счётчик paid станет равен 4.
Ответ: После добавления новой строки paid результат будет cancelled=1, new=2, paid=4.
Задача 2. Сложить выручку по категориям
Рабочий вопросЕсть продажи разных категорий. Нужно узнать, какие категории принесли больше денег за период.
ДанныеCREATE TABLE sales(id INTEGER, category TEXT, revenue INTEGER);
INSERT INTO sales VALUES
(1,'books',300),(2,'courses',900),(3,'books',250),(4,'templates',420),(5,'courses',300);
ЗапросSELECT category, SUM(revenue) AS revenue
FROM sales
GROUP BY category
ORDER BY revenue DESC, category;
Ожидаемый результат[["courses", 1200], ["books", 550], ["templates", 420]]
Почему работаетSUM складывает revenue только внутри текущей категории.
Сортировка по revenue DESC показывает самые денежные категории сверху.
Дополнительная сортировка по category делает порядок предсказуемым при равенстве сумм.
Где легко ошибитьсяНельзя читать этот отчёт как прибыль: здесь нет комиссий, налогов и себестоимости.
Самостоятельная проверкаДобавьте продажу templates на 900. Какая категория выйдет первой?
Ответ: templates станет первой с 1320, потому что 420 + 900 больше 1200.
Задача 3. Найти средний чек клиента
Рабочий вопросМенеджер хочет сравнить клиентов по среднему заказу, а не по общей сумме покупок.
ДанныеCREATE TABLE orders(client TEXT, total INTEGER);
INSERT INTO orders VALUES
('Анна',1000),('Анна',500),('Илья',900),('Олег',300),('Олег',900);
ЗапросSELECT client, ROUND(AVG(total), 2) AS avg_total
FROM orders
GROUP BY client
ORDER BY avg_total DESC, client;
Ожидаемый результат[["Илья", 900.0], ["Анна", 750.0], ["Олег", 600.0]]
Почему работаетAVG считает среднее значение total внутри группы клиента.
Конец ознакомительного фрагмента.
Текст предоставлен ООО «Литрес».
Прочитайте эту книгу целиком, купив полную легальную версию на Литрес.
Безопасно оплатить книгу можно банковской картой Visa, MasterCard, Maestro, со счета мобильного телефона, с платежного терминала, в салоне МТС или Связной, через PayPal, WebMoney, Яндекс.Деньги, QIWI Кошелек, бонусными картами или другим удобным Вам способом.




