Как работает SQL запрос с полным набором полей без агрегатных функций и GROUP BY по этим же полям
Что проверяют
Понимаете ли вы, что GROUP BY по всем выбранным колонкам без агрегатов схлопывает дубли и по смыслу равен SELECT DISTINCT. Следом обычно спрашивают, отличается ли такой запрос от DISTINCT по плану и когда группировкой маскируют ошибку в соединении.
Как отвечать
Начните с логического порядка выполнения: FROM и JOIN, затем WHERE, GROUP BY, HAVING, SELECT, ORDER BY, LIMIT. Запрос SELECT city, segment FROM orders WHERE dt >= '2026-01-01' GROUP BY city, segment берёт отфильтрованные строки, раскладывает их по группам с одинаковой парой значений и из каждой группы возвращает одну строку. Итог: уникальные комбинации, ровно как у SELECT DISTINCT city, segment.
Детали, которые отличают сильный ответ:
- план: в PostgreSQL оба варианта обычно дают одинаковый
HashAggregateили сортировку с последующим схлопыванием соседних строк. В Spark оптимизатор сам переписываетDISTINCTв агрегацию, так что разницы в скорости нет; - NULL: при группировке все
NULLв колонке попадают в одну группу, хотя сравнениеNULL = NULLвWHEREне даёт истину; - уникальная колонка: если в списке есть первичный ключ, дублей не будет, и группировка становится лишней работой над всей выборкой;
- порядок:
GROUP BYне гарантирует сортировку. В MySQL до 8.0 результат выходил отсортированным, сейчас нет, нужен явныйORDER BY; - поиск дублей: та же группировка с
HAVING COUNT(*) > 1показывает повторяющиеся комбинации. В pandas аналогиdrop_duplicates()иgroupby(...).size().
Скажите и про выбор: для дедупликации понятнее DISTINCT, а GROUP BY берут, когда скоро понадобится агрегат.
Где спотыкаются
Говорят, что без агрегатов каждая строка результата уникальна «сама собой». Без группировки или DISTINCT дубли в выборке остаются.
Лечат группировкой дубли после JOIN. Если строки размножились из-за соединения один ко многим, нужно найти причину, а не прятать её, иначе суммы в соседних отчётах и признаки для модели разъедутся.
Рассчитывают на порядок строк после GROUP BY и строят на нём выгрузку или разбиение на обучающую и тестовую выборки.