Для чего нужен оператор GROUP BY в SQL?

«Для чего нужен оператор GROUP BY в SQL?» — вопрос из категории Базы данных, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

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

Практический пример из работы с интернет-магазином:

-- Получить общую выручку и количество заказов по каждой категории товаров за последний месяц
SELECT 
    p.category_id,
    c.name AS category_name,
    COUNT(DISTINCT o.id) AS total_orders, -- Количество уникальных заказов
    SUM(oi.quantity) AS total_items_sold, -- Общее количество проданных единиц
    SUM(oi.quantity * oi.unit_price) AS total_revenue -- Общая выручка
FROM order_items oi
JOIN orders o ON oi.order_id = o.id
JOIN products p ON oi.product_id = p.id
JOIN categories c ON p.category_id = c.id
WHERE o.order_date >= DATE_SUB(NOW(), INTERVAL 1 MONTH)
GROUP BY p.category_id, c.name -- Группируем по ID и названию категории
ORDER BY total_revenue DESC;

Ключевые правила и особенности:

  • Все столбцы в секции SELECT, которые не являются аргументами агрегатных функций, должны быть указаны в GROUP BY. В современных СУБД (MySQL 5.7+, PostgreSQL) это правило строгое.
  • GROUP BY часто используется вместе с HAVING для фильтрации уже сгруппированных результатов (в отличие от WHERE, который фильтрует строки до группировки).
    -- Найти категории, в которых было продано более 1000 единиц товара
    SELECT category_id, SUM(quantity) AS total_sold
    FROM order_items
    GROUP BY category_id
    HAVING total_sold > 1000;
  • Группировка может выполняться по вычисляемым выражениям или функциям.
    -- Группировка заказов по неделям
    SELECT YEARWEEK(order_date) AS order_week, COUNT(*) AS orders_count
    FROM orders
    GROUP BY YEARWEEK(order_date);

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