DISTINCT

DISTINCT удаляет одинаковые строки из результата после формирования выбранных выражений.

SELECT DISTINCT state
FROM orders;

Для нескольких столбцов уникальна вся комбинация:

SELECT DISTINCT user_id, state
FROM orders;

DISTINCT и NULL

Для удаления дубликатов несколько NULL в одном выражении считаются неразличимыми и дают одну строку. Это отличается от обычного NULL = NULL, которое возвращает UNKNOWN.

Не маскировать ошибочный JOIN

SELECT DISTINCT u.id, u.email
FROM users AS u
JOIN orders AS o ON o.user_id = u.id
WHERE o.state = 'PAID';

Если нужны только пользователи с заказом, намерение точнее выражает EXISTS. DISTINCT после случайного размножения строк может скрыть ошибку и добавить дорогую сортировку/хеширование.

DISTINCT внутри агрегата

SELECT COUNT(DISTINCT user_id)
FROM orders;

Это число пользователей с заказами. Для нескольких выражений синтаксис зависит от СУБД.

DISTINCT ON

Некоторые СУБД дают нестандартные расширения для «первой строки в группе». Переносимый вариант обычно строят с оконной функцией ROW_NUMBER() и явным порядком.

Ловушки

  • DISTINCT не гарантирует сортировку.
  • Добавление выбранного столбца меняет критерий уникальности.
  • Удаление дубликатов может потребовать много памяти и временного I/O.

Связано: Оператор EXISTS, Агрегатные функции, Оператор GROUP BY, SQL оценка производительности.

Вопросы

По каким столбцам работает DISTINCT? По всей комбинации выражений в SELECT.

Сортирует ли он результат? Нет, даже если план использовал сортировку.

Почему DISTINCT бывает «запахом»? Может скрывать неверную кардинальность JOIN.

Как посчитать уникальных пользователей? COUNT(DISTINCT user_id).