Группировка данных: GROUP BY, группировка по нескольким полям

🤔 Зачем нужна группировка данных?

В SQL часто требуется не просто выбирать данные, а анализировать их: считать суммы, находить средние значения, определять количество записей по категориям. Вот тут-то и приходит на помощь GROUP BY — мощный инструмент для агрегации данных.

Без группировки:

SELECT department, salary 
FROM employees;

Просто список всех зарплат — не очень информативно.

С группировкой:

SELECT department, AVG(salary) as avg_salary
FROM employees
GROUP BY department;

Теперь видим среднюю зарплату по отделам — гораздо полезнее!


🛠️ Базовый синтаксис GROUP BY

Ключевые элементы:

  1. Указываем поля для группировки после GROUP BY
  2. В SELECT включаем только:
  3. Поля группировки
  4. Агрегатные функции (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)
  • С сортировкой по дате и выручке

🎯 Главные выводы

  1. GROUP BY превращает сырые данные в аналитику
  2. Можно группировать по одному или нескольким полям
  3. В SELECT — только поля группировки и агрегатные функции
  4. HAVING фильтрует результаты группировки
  5. Группировка работает с выражениями и функциями

Попробуйте применить эти приёмы к своим данным — вы удивитесь, какие инсайты можно обнаружить! 🔍

Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео