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)считает уникальные значения.