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).