✏️ Explanatory Question

Duplicate Emails — find emails that appear more than once

👁 7 Views
📘 Detailed Answer
🟢 Easy
💡

Answer with Explanation

144

Duplicate Emails — find emails that appear more than once

Level: Coding Round — A LeetCode warm-up classic; the foundation for data-cleaning and dedup tasks.

The Puzzle: Given a person table, report all email addresses that appear more than once. This is the classic first step before de-duplicating records.

Sample Data — person

idemail
1rumman@x.com
2krushna@x.com
3rumman@x.com
4swetha@x.com
5krushna@x.com

Expected Output

Email
rumman@x.com
krushna@x.com

rumman@x.com appears twice (ids 1, 3) and krushna@x.com twice (ids 2, 5). swetha@x.com is unique → excluded.

The core technique — GROUP BY + HAVING: Group rows by email, then use HAVING COUNT(*) > 1 to keep only groups with more than one row. Remember: WHERE filters individual rows (before grouping), while HAVING filters the grouped result — and only HAVING can use aggregate functions like COUNT().

Solution 1 — GROUP BY + HAVING (the standard answer)

SELECT email AS Email
FROM person
GROUP BY email
HAVING COUNT(*) > 1;

Solution 2 — Correlated Subquery

SELECT DISTINCT p1.email AS Email
FROM person p1
WHERE (SELECT COUNT(*) FROM person p2 WHERE p2.email = p1.email) > 1;
-- Works, but re-counts per row; GROUP BY is cleaner and faster

Solution 3 — Self-Join (shows the technique)

SELECT DISTINCT p1.email AS Email
FROM person p1
JOIN person p2 ON p1.email = p2.email AND p1.id <> p2.id;
-- If an email matches another row with a different id, it's a duplicate

Case-sensitivity gotcha: By default, MySQL string comparison depends on the column's collation. With a case-insensitive collation (like utf8mb4_0900_ai_ci), Rumman@x.com and rumman@x.com are treated as the same email. If you need exact case matching, group on BINARY email or a case-sensitive collation. Mention this — email dedup is a real-world case-sensitivity trap.

Follow-Up — Delete Duplicates, Keep the Lowest id

-- Natural extension: remove the duplicate rows, keeping one per email
DELETE p1
FROM person p1
JOIN person p2 ON p1.email = p2.email AND p1.id > p2.id;
-- Keeps the smallest id for each email; deletes the rest

-- Then prevent future duplicates
ALTER TABLE person ADD UNIQUE (email);

Interviewer follow-up: "Return each duplicate email along with how many times it appears and the list of ids." → Extend the GROUP BY: SELECT email, COUNT(*) AS cnt, GROUP_CONCAT(id ORDER BY id) AS ids FROM person GROUP BY email HAVING COUNT(*) > 1. GROUP_CONCAT gathers all the ids per group into one field — useful for reporting exactly which rows are duplicated.