Для чего нужна группировка по email при группировке по пользователю
Что проверяют
По сути это вопрос про SQL, а не про Go: знаете ли вы правило GROUP BY и что такое функциональная зависимость. Типичная ситуация: сервис на Go через pgx или database/sql считает заказы по пользователю, выводит его email, и запрос падает с ошибкой. Следом спрашивают, меняет ли email в группировке результат и как написать запрос эффективнее.
Как отвечать
Правило стандарта SQL: каждая колонка в SELECT без агрегата должна стоять в GROUP BY или однозначно определяться сгруппированными колонками. В запросе SELECT u.id, u.email, count(*) FROM users u JOIN orders o ON o.user_id = u.id GROUP BY u.id, u.email группировка фактически идёт по id, а email добавлен, чтобы его можно было вывести. Групп от этого не прибавится: у одного id один email.
Нюансы по базам:
- PostgreSQL: если
u.idэто первичный ключusers, достаточноGROUP BY u.id, аu.emailвыбирать можно, база видит зависимость от ключа. С уникальным индексом вместо первичного ключа это не работает, и запрос падает сmust appear in the GROUP BY clause or be used in an aggregate function; - MySQL: с режимом
ONLY_FULL_GROUP_BY, включённым по умолчанию, поведение похожее. Без него база вернёт произвольное значение из группы; - вариант лучше: агрегировать по
user_idв подзапросе или CTE и потом присоединитьusers. Группировка идёт по узкому целочисленному ключу, а не по длинным строкам, и лишние колонки в неё не попадают.
Группировка только по email, без id, это уже другой запрос: он склеит разных пользователей с одинаковым адресом, если email не уникален.
Где спотыкаются
Думают, что email в GROUP BY меняет разбиение на группы. При группировке по первичному ключу не меняет, это требование синтаксиса.
«Чинят» ошибку в MySQL, отключая ONLY_FULL_GROUP_BY. Ошибка пропадает, а в выдаче появляются случайные значения из группы.
Группируют по email вместо id, не проверив уникальность и регистр. В отчёте два аккаунта сливаются в один, а Ivan@mail.ru и ivan@mail.ru без нормализации наоборот считаются разными людьми.