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. А на странице примеры вопросов можно посмотреть, что спрашивают на реальных собеседованиях.