Условие
В таблице users(id, email) найдите все email-адреса, которые встречаются больше одного раза.
Решение
Подход
Группировка по email и фильтрация через HAVING COUNT(*) > 1. Альтернатива — оконная функция COUNT() OVER, она удобнее, когда хочется сразу видеть и сами строки с дубликатами, а не только email-ы.
Реализация
-- Просто email-ы с дубликатами
SELECT email, COUNT(*) AS cnt
FROM users
GROUP BY email
HAVING COUNT(*) > 1
ORDER BY cnt DESC;
-- Все строки, у которых email — дубликат
SELECT id, email
FROM (
SELECT id, email, COUNT(*) OVER (PARTITION BY email) AS cnt
FROM users
) t
WHERE cnt > 1
ORDER BY email;Если задача — удалить дубликаты, оставив самую старую запись:
DELETE FROM users
WHERE id IN (
SELECT id FROM (
SELECT id,
ROW_NUMBER() OVER (PARTITION BY email ORDER BY id) AS rn
FROM users
) t
WHERE rn > 1
);Подводные камни
- Чувствительность к регистру.
Vasya@mail.ruиvasya@mail.ru— формально разные email, но фактически один. ИспользуйтеLOWER(email)в группировке. - Пробелы по краям.
' vasya@mail.ru'≠'vasya@mail.ru'. ПрименяйтеTRIM. - NULL-email.
COUNT(*)посчитает строки сNULL-email вместе. Если хотите исключить —WHERE email IS NOT NULL. HAVING COUNT(*) > 1нельзя писать безGROUP BYв большинстве СУБД — частая ошибка джунов.
Эталонный ответ
SELECT email FROM users GROUP BY email HAVING COUNT(*) > 1. Перед группировкой полезно нормализовать email через LOWER(TRIM(email)).