DISTINCT vs GROUP BY в SQL — в чём разница и когда что использовать
Коротко
DISTINCT убирает дублирующиеся строки из результата. GROUP BY группирует строки для агрегации (COUNT, SUM, AVG). Иногда они дают одинаковый результат, но задачи у них разные — и на собеседовании важно это объяснить.
Что такое DISTINCT
DISTINCT — это модификатор SELECT, который убирает полные дубликаты из результата. Если две строки совпадают по всем выбранным колонкам — остаётся одна.
SELECT DISTINCT city
FROM users;Вернёт список уникальных городов — без повторов.
DISTINCT работает по всем колонкам в SELECT. Если указать несколько — дубликаты убираются по комбинации:
SELECT DISTINCT city, department
FROM employees;Здесь уникальность определяется парой (city, department). Москва + Аналитика и Москва + Маркетинг — это две разные строки.
Что такое GROUP BY
GROUP BY группирует строки с одинаковыми значениями в указанных колонках. Сам по себе он бесполезен — его сила в комбинации с агрегатными функциями.
SELECT city, COUNT(*) AS user_count
FROM users
GROUP BY city;Для каждого города получаем количество пользователей. GROUP BY собирает строки в группы, а COUNT считает размер каждой группы.
SELECT department, AVG(salary) AS avg_salary, MAX(salary) AS max_salary
FROM employees
GROUP BY department;Средняя и максимальная зарплата по отделам. Без GROUP BY агрегация работала бы по всей таблице целиком.
Ключевые отличия
| DISTINCT | GROUP BY | |
|---|---|---|
| Задача | Убрать дубликаты | Сгруппировать для агрегации |
| Агрегатные функции | Не нужны | Обычно используются |
| Что возвращает | Уникальные строки | Одну строку на группу |
| Работает с | Всеми колонками в SELECT | Указанными колонками |
| Читаемость | Проще для дедупликации | Проще для аналитики |
Когда использовать DISTINCT
Когда нужен список уникальных значений без подсчётов и агрегации.
Уникальные источники трафика:
SELECT DISTINCT utm_source
FROM onboarding_runs
WHERE utm_source IS NOT NULL;Пользователи, которые хоть раз ответили правильно:
SELECT DISTINCT user_id
FROM training_events
WHERE is_correct = TRUE;Ещё DISTINCT часто используется внутри агрегатных функций — COUNT(DISTINCT column):
SELECT COUNT(DISTINCT user_id) AS unique_users
FROM training_events;Количество уникальных пользователей, которые отвечали на вопросы. Без DISTINCT COUNT посчитает все строки, включая повторных.
Когда использовать GROUP BY
Когда нужна агрегация — подсчёты, суммы, средние значения по группам.
Количество ответов по темам:
SELECT topic, COUNT(*) AS answers
FROM training_events
GROUP BY topic
ORDER BY answers DESC;Конверсия по источникам трафика:
SELECT utm_source,
COUNT(*) AS total,
COUNT(*) FILTER (WHERE status = 'completed') AS completed
FROM onboarding_runs
GROUP BY utm_source;GROUP BY также нужен для фильтрации групп через HAVING — то, что WHERE не умеет:
SELECT topic, COUNT(DISTINCT user_id) AS users
FROM training_events
GROUP BY topic
HAVING COUNT(DISTINCT user_id) > 100;Темы, которые изучают более 100 уникальных пользователей.
Когда результат одинаковый
Если нужен просто список уникальных значений одной колонки, DISTINCT и GROUP BY дадут одинаковый результат:
-- Вариант 1
SELECT DISTINCT city FROM users;
-- Вариант 2
SELECT city FROM users GROUP BY city;Оба запроса вернут один и тот же набор строк. В PostgreSQL оптимизатор обычно строит одинаковый план выполнения для обоих вариантов — разницы в производительности нет.
Совет для собеседования: если задача — получить уникальные значения, используйте DISTINCT. Это яснее по смыслу. GROUP BY без агрегатных функций выглядит как недописанный запрос.
Типичная ошибка
Использовать GROUP BY вместо DISTINCT, когда агрегация не нужна:
-- Так себе — GROUP BY без агрегации
SELECT department
FROM employees
GROUP BY department;
-- Лучше — сразу понятно, что нужны уникальные значения
SELECT DISTINCT department
FROM employees;Результат одинаковый, но DISTINCT читается проще. Коллега (или интервьюер), увидев GROUP BY, будет искать COUNT или SUM — и не найдёт.
Обратная ошибка — использовать DISTINCT, когда нужна группировка с подсчётом:
-- Неправильно — DISTINCT не считает
SELECT DISTINCT department FROM employees;
-- Правильно — нужен COUNT
SELECT department, COUNT(*) AS cnt
FROM employees
GROUP BY department;Вопросы с собеседований
— DISTINCT и GROUP BY дают одинаковый результат. Когда что использовать? — DISTINCT — для дедупликации, GROUP BY — для агрегации. Если нужны только уникальные значения без подсчётов — DISTINCT. Если нужны COUNT, SUM, AVG — GROUP BY.
— Что быстрее — DISTINCT или GROUP BY? — В PostgreSQL обычно одинаково: оптимизатор строит идентичный план. В других СУБД может отличаться — но разница редко значима.
— Можно ли использовать DISTINCT с несколькими колонками? — Да. DISTINCT убирает дубликаты по комбинации всех колонок в SELECT. Каждая уникальная комбинация значений — отдельная строка.
— Чем COUNT(DISTINCT col) отличается от COUNT(col)? — COUNT(col) считает все не-NULL значения, включая повторы. COUNT(DISTINCT col) считает только уникальные не-NULL значения.
— Зачем писать GROUP BY, если DISTINCT делает то же самое? — GROUP BY позволяет использовать агрегатные функции и HAVING. DISTINCT — нет. Они решают разные задачи, даже если иногда результат совпадает.
Потренируйтесь решать задачи — откройте тренажёр с 1500+ вопросами для подготовки к собеседованиям аналитиков.
FAQ
Можно ли использовать DISTINCT и GROUP BY в одном запросе?
Да. Частый случай — COUNT(DISTINCT col) внутри GROUP BY:
SELECT department, COUNT(DISTINCT city) AS cities
FROM employees
GROUP BY department;Количество уникальных городов в каждом отделе.
DISTINCT работает только с одной колонкой?
Нет. DISTINCT работает со всеми колонками в SELECT. Уникальность определяется по комбинации значений всех указанных колонок.
В каких случаях GROUP BY эффективнее DISTINCT?
Когда нужна агрегация. DISTINCT не умеет считать, суммировать или усреднять — он только убирает дубликаты. Для аналитических задач GROUP BY незаменим.
Где потренировать эти запросы?
В SQL-тренажёре Карьерника — 500+ вопросов по SQL, включая DISTINCT и GROUP BY. А на странице примеры вопросов можно посмотреть, что спрашивают на реальных собеседованиях.