Finding duplicates means identifying rows that repeat a value (or combination of values) that should be unique — duplicate emails, repeated orders, doubled records from a bad import. The standard technique is GROUP BY the columns that should be unique and keep groups with COUNT(*) > 1.
Duplicate data is one of the most common defects testers hunt, arising from missing unique constraints, retried operations, or faulty imports. The canonical detection query groups by the column(s) expected to be unique and filters HAVING COUNT(*) > 1, returning each duplicated value with its occurrence count. To see the actual duplicate rows (not just the values), you either join that result back to the table or use a window function (ROW_NUMBER partitioned by the key) and select rows where the row number is greater than 1 — which also underpins de-duplication, since those are the rows you'd delete to keep one copy. Composite duplicates (same first_name + last_name + dob) group by all the relevant columns. A subtlety: values differing only by case or trailing whitespace ('Test@x.com' vs 'test@x.com ') may be logical duplicates that an exact GROUP BY misses, so normalization (LOWER, TRIM) is often needed for real-world duplicate detection.
After a signup bug report, a tester checks for duplicate accounts with SELECT email, COUNT(*) FROM users GROUP BY email HAVING COUNT(*) > 1 — instantly listing every email registered more than once, confirming the missing unique constraint.
-- Which emails are duplicated, and how many times?
SELECT email, COUNT(*) AS occurrences
FROM users
GROUP BY email
HAVING COUNT(*) > 1
ORDER BY occurrences DESC;
-- Catch case/whitespace duplicates too
SELECT LOWER(TRIM(email)) AS normalized_email, COUNT(*) AS occurrences
FROM users
GROUP BY LOWER(TRIM(email))
HAVING COUNT(*) > 1;
-- See the actual extra rows (row number > 1 = duplicates to remove)
SELECT * FROM (
SELECT id, email,
ROW_NUMBER() OVER (PARTITION BY email ORDER BY id) AS rn
FROM users
) t
WHERE rn > 1;Scenario: A bug report says some customers receive two confirmation emails. A tester runs SELECT email, COUNT(*) FROM users GROUP BY email HAVING COUNT(*) > 1 and gets zero rows, concluding there are no duplicate accounts — yet the duplicates clearly exist. What could the exact-match query be missing, and how do you find the real duplicates?