Группировка данных: GROUP BY, группировка по нескольким полям
🤔 Зачем нужна группировка данных?
В SQL часто требуется не просто выбирать данные, а анализировать их: считать суммы, находить средние значения, определять количество записей по категориям. Вот тут-то и приходит на помощь GROUP BY — мощный инструмент для агрегации данных.
Без группировки:
SELECT department, salary
FROM employees;
Просто список всех зарплат — не очень информативно.
С группировкой:
SELECT department, AVG(salary) as avg_salary
FROM employees
GROUP BY department;
Теперь видим среднюю зарплату по отделам — гораздо полезнее!
🛠️ Базовый синтаксис GROUP BY
Ключевые элементы:
- Указываем поля для группировки после
GROUP BY - В
SELECTвключаем только: - Поля группировки
- Агрегатные функции (COUNT, SUM, AVG и т.д.)
Пример с подсчётом количества:
SELECT product_category, COUNT(*) as product_count
FROM products
GROUP BY product_category;
Результат — количество товаров в каждой категории.
🔢 Группировка по нескольким полям
Когда нужно анализировать данные по комбинациям значений — группируем по нескольким столбцам. Порядок полей влияет на результат!
Пример для интернет-магазина:
SELECT
product_category,
supplier_region,
COUNT(*) as products_count,
AVG(price) as avg_price
FROM products
GROUP BY product_category, supplier_region;
Теперь видим:
- Сколько товаров каждой категории из каждого региона
- Их среднюю цену
🚨 Частые ошибки и как их избежать
Ошибка 1: Несоответствие полей в SELECT и GROUP BY
❌ Неверно:
SELECT product_name, COUNT(*) -- product_name не в GROUP BY!
FROM products
GROUP BY product_category;
✔️ Правильно:
SELECT product_category, COUNT(*)
FROM products
GROUP BY product_category;
Ошибка 2: Путаница с WHERE и HAVING
WHEREфильтрует ДО группировкиHAVINGфильтрует ПОСЛЕ группировки
Пример:
SELECT department, AVG(salary) as avg_salary
FROM employees
WHERE hire_date > '2020-01-01' -- фильтр по дате приёма
GROUP BY department
HAVING AVG(salary) > 100000; -- фильтр по средней зарплате
🏆 Продвинутые приёмы
GROUP BY с выражениями
Можно группировать по результатам вычислений:
SELECT
EXTRACT(YEAR FROM order_date) as year,
COUNT(*) as orders_count
FROM orders
GROUP BY EXTRACT(YEAR FROM order_date);
ROLLUP — группировка с промежуточными итогами
SELECT
department,
job_title,
SUM(salary) as total_salary
FROM employees
GROUP BY ROLLUP(department, job_title);
Выведет итоги по отделам, должностям и общий итог.
💡 Практический кейс: Анализ продаж
Разберём реальный пример для интернет-магазина:
SELECT
c.country,
p.category,
DATE_TRUNC('month', o.order_date) as month,
COUNT(DISTINCT o.order_id) as orders,
SUM(oi.quantity * oi.price) as revenue
FROM orders o
JOIN order_items oi ON o.order_id = oi.order_id
JOIN products p ON oi.product_id = p.product_id
JOIN customers c ON o.customer_id = c.customer_id
WHERE o.order_date BETWEEN '2023-01-01' AND '2023-12-31'
GROUP BY c.country, p.category, DATE_TRUNC('month', o.order_date)
HAVING SUM(oi.quantity * oi.price) > 10000
ORDER BY month, revenue DESC;
Что анализируем:
- Выручку по странам, категориям и месяцам
- Только значимые продажи (>10 000)
- С сортировкой по дате и выручке
🎯 Главные выводы
GROUP BYпревращает сырые данные в аналитику- Можно группировать по одному или нескольким полям
- В
SELECT— только поля группировки и агрегатные функции HAVINGфильтрует результаты группировки- Группировка работает с выражениями и функциями
Попробуйте применить эти приёмы к своим данным — вы удивитесь, какие инсайты можно обнаружить! 🔍