Как проверить уникальность в SQL
Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.
Три способа проверить уникальность
- COUNT vs COUNT DISTINCT — быстро узнать, есть ли дубли
- GROUP BY + HAVING — найти конкретные дубли
- UNIQUE constraint — запретить дубли на уровне БД
1. Есть ли вообще дубликаты
SELECT
COUNT(*) AS total,
COUNT(DISTINCT email) AS unique_emails,
COUNT(*) - COUNT(DISTINCT email) AS duplicates
FROM users;Если duplicates = 0 — уникальность соблюдается.
2. Найти дубли по одной колонке
SELECT email, COUNT(*) AS cnt
FROM users
GROUP BY email
HAVING COUNT(*) > 1;3. Найти дубли по комбинации
SELECT first_name, last_name, birth_date, COUNT(*)
FROM users
GROUP BY first_name, last_name, birth_date
HAVING COUNT(*) > 1;4. Уникальность без учёта регистра
SELECT LOWER(email), COUNT(*) AS cnt
FROM users
GROUP BY LOWER(email)
HAVING COUNT(*) > 1;5. Уникальность без пробелов
SELECT TRIM(name), COUNT(*) AS cnt
FROM users
GROUP BY TRIM(name)
HAVING COUNT(*) > 1;6. Уникальность с учётом NULL
-- NULL группируется вместе (не все хотят)
SELECT email, COUNT(*)
FROM users
WHERE email IS NOT NULL
GROUP BY email
HAVING COUNT(*) > 1;7. UNIQUE constraint (запрет дублей)
-- при создании таблицы
CREATE TABLE users (
id INT PRIMARY KEY,
email VARCHAR(255) UNIQUE
);
-- добавить к существующей
ALTER TABLE users
ADD CONSTRAINT uq_users_email UNIQUE (email);
-- UNIQUE на несколько колонок
ALTER TABLE order_items
ADD CONSTRAINT uq_order_product UNIQUE (order_id, product_id);После UNIQUE constraint INSERT дубля даст ошибку.
8. Посмотреть существующие unique constraints
Postgres
SELECT conname, contype, pg_get_constraintdef(oid)
FROM pg_constraint
WHERE contype = 'u' AND conrelid = 'users'::regclass;MySQL
SHOW INDEX FROM users WHERE Non_unique = 0;9. Проверка перед INSERT
-- INSERT только если такой email не существует
INSERT INTO users (email, name)
SELECT 'alice@example.com', 'Alice'
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE email = 'alice@example.com'
);Или ON CONFLICT (Postgres):
INSERT INTO users (email, name)
VALUES ('alice@example.com', 'Alice')
ON CONFLICT (email) DO NOTHING;Частые ошибки
NULL при сравнении
COUNT(*) vs COUNT(col) — разница. COUNT(col) игнорирует NULL.
UNIQUE с NULL
В UNIQUE несколько NULL разрешены (так в большинстве СУБД). Если это проблема — используйте NOT NULL UNIQUE.
Регистр
Alice ≠ alice в большинстве collations. Для case-insensitive используйте LOWER() или CITEXT в Postgres.
Связанные темы
FAQ
Как проверить uniqueness в огромной таблице?
COUNT DISTINCT на индексированной колонке — относительно быстро. Approximate count (uniq в ClickHouse) — ещё быстрее.
UNIQUE и PRIMARY KEY — это одно?
PK = UNIQUE + NOT NULL + один на таблицу. UNIQUE может быть несколько, с NULL.
Чем проверять уникальность в ETL?
Встраивайте в pipeline COUNT vs COUNT(DISTINCT) как sanity check. dbt tests делают это автоматически.
Тренируйте SQL — откройте тренажёр с 1500+ вопросами для собесов.