DISTINCT и уникальность строк

Что такое DISTINCT, как он работает по нескольким колонкам и чем отличается от GROUP BY.

DISTINCT убирает дубликаты строк из результата, рассматривая всю выбранную строку целиком, а не отдельную колонку.

Вопрос: DISTINCT по нескольким колонкам

Частая ловушка: думают, что SELECT DISTINCT a, b уберёт дубли по a. На самом деле уникальной считается пара (a, b). Проверим.

CREATE TABLE visits (
    id    INTEGER PRIMARY KEY,
    user  TEXT,
    city  TEXT
);

INSERT INTO visits (user, city) VALUES
    ('Аня',   'Москва'),
    ('Аня',   'Москва'),
    ('Аня',   'Казань'),
    ('Борис', 'Москва');

SELECT DISTINCT user, city
FROM visits
ORDER BY user, city;

Вывод:

Аня|Казань
Аня|Москва
Борис|Москва

Полный дубль (Аня, Москва) схлопнулся в одну строку. Но (Аня, Москва) и (Аня, Казань) — разные пары, обе остались. DISTINCT смотрит на строку целиком.

DISTINCT по одной колонке

Если нужны именно уникальные пользователи без городов — выбираем одну колонку:

CREATE TABLE visits (
    id    INTEGER PRIMARY KEY,
    user  TEXT,
    city  TEXT
);

INSERT INTO visits (user, city) VALUES
    ('Аня',   'Москва'),
    ('Аня',   'Казань'),
    ('Борис', 'Москва');

SELECT DISTINCT user
FROM visits
ORDER BY user;

Вывод:

Аня
Борис

DISTINCT vs GROUP BY

SELECT DISTINCT user FROM visits и SELECT user FROM visits GROUP BY user дают одинаковый набор уникальных значений. Разница в намерении: GROUP BY нужен, когда вы собираетесь что-то агрегировать (COUNT, SUM), а DISTINCT — когда просто хотите убрать дубликаты. Если агрегатов нет, выбирайте DISTINCT как более явный по смыслу.

COUNT(DISTINCT …)

Очень частый практический случай — посчитать число уникальных значений:

CREATE TABLE visits (
    id    INTEGER PRIMARY KEY,
    user  TEXT,
    city  TEXT
);

INSERT INTO visits (user, city) VALUES
    ('Аня',   'Москва'),
    ('Аня',   'Казань'),
    ('Борис', 'Москва'),
    ('Борис', 'Москва');

SELECT COUNT(*)            AS vsego_strok,
       COUNT(DISTINCT user) AS unikalnyh_polzovateley
FROM visits;

Вывод:

4|2

Всего 4 строки, но уникальных пользователей только 2 — COUNT(DISTINCT user) это и показывает.

Итог

  • DISTINCT убирает дубли по всей выбранной строке, а не по одной колонке.
  • Для уникальных значений одной колонки — выбирайте только её.
  • DISTINCT и GROUP BY без агрегатов дают тот же результат; COUNT(DISTINCT col) считает уникальные значения.
Проверьте себя
1. Что считает уникальным SELECT DISTINCT a, b?
AТолько значения a
BПару значений (a, b) целиком
CТолько значения b
DКаждую колонку отдельно
2. Чем DISTINCT отличается от GROUP BY без агрегатов?
AРезультат разный
BРезультат одинаковый, отличается лишь намерение
CDISTINCT медленнее всегда
DGROUP BY не убирает дубли
3. Что вернёт COUNT(DISTINCT user) при 4 строках с двумя разными user?
A4
B2
C1
D0
Поддержать проект