GROUP BY используется для группировки строк и агрегирования данных, но при неправильном применении может вызывать серьезные ошибки или неоптимальную работу.
Ключевые тонкости:
Пример:
SELECT customer_id, COUNT(*) as orders FROM orders WHERE order_date >= '2024-01-01' GROUP BY customer_id HAVING COUNT(*) > 10;
Можно ли в SELECT после GROUP BY ссылаться на поля, которые не были указаны ни в GROUP BY, ни в агрегатной функции?
Ответ: Нет, это приведёт к ошибке в большинстве SQL-реализаций (например, в MS SQL, PostgreSQL). Некоторые специфические БД могут показать случайное, неверное значение (особенно в MySQL с sql_mode 'ONLY_FULL_GROUP_BY' выключен), но это поведение некорректно и не гарантируется стандартом. Корректный пример:
SELECT department, AVG(salary) FROM employees GROUP BY department;
История
В e-commerce проекте отчет "выручка по товарам" готовили запросом SELECT sku, price, SUM(qty) FROM orders GROUP BY sku. Не учли: price не попал в GROUP BY и был вне агрегатной функции, результат — MySQL возвращал первое попавшееся значение цены, что при акции дало серьёзные ошибки в отчёте. Исправление — либо добавить price в GROUP BY, либо использовать агрегатную функцию.
История
В BI-проекте сложный отчет с несколькими JOIN и GROUP BY выполнялся по 80 минут вместо плановых 3. После анализа выяснили: отсутствовали индексы по полю из GROUP BY и фильтрации, создавались огромные временные таблицы для агрегации. Решение — оптимизация индексов и переписка запроса с табличными выражениями.
История
Разработчик применил HAVING для фильтрации значений по неагрегированному атрибуту пользователя. В результате сервер отработал группировку по всем данным, а потом убрал их по HAVING, снизив производительность. Исправили — вынесли эту проверку в WHERE, чтобы сужать выборку до агрегации.