Как сгруппировать данные и посчитать по группам (GROUP BY)?
У меня таблица заказов, в каждой строке покупатель и сумма. Хочу узнать, сколько заказов сделал каждый покупатель. Как сгруппировать строки и посчитать по группам в SQL? Что вообще делает GROUP BY?
2 ответа
GROUP BY схлопывает строки с одинаковым значением в одну группу, а агрегатные функции (COUNT, SUM, AVG…) считаются внутри каждой группы:
SELECT customer_id, COUNT(*) AS orders_count
FROM orders
GROUP BY customer_id;
Результат — по одной строке на каждого покупателя и число его заказов рядом.
Можно считать несколько агрегатов сразу:
SELECT customer_id,
COUNT(*) AS orders_count,
SUM(total) AS total_spent
FROM orders
GROUP BY customer_id;
Главное правило, на котором спотыкаются все новички: в SELECT можно класть либо столбцы из GROUP BY, либо агрегатные функции. Нельзя написать SELECT customer_id, product_name с GROUP BY customer_id — потому что у одного покупателя много разных товаров, и СУБД не знает, какой показать. PostgreSQL прямо выдаст ошибку, а MySQL раньше молча возвращал случайный — это источник коварных багов.
Группировать можно и по нескольким столбцам — тогда группа определяется их комбинацией:
GROUP BY customer_id, status
Аналогия, которая помогает: GROUP BY — это как разложить колоду карт по мастям, а потом посчитать карты в каждой стопке. Сами стопки — это группы (значения столбца), а COUNT/SUM — что вы делаете с каждой стопкой. Без агрегатной функции группировка почти не имеет смысла — вы просто получите список уникальных значений, как от DISTINCT.