How to Find Duplicate Rows in SQL Server

Last updated July 25, 2026 · By the SaturnSQL team

GROUP BY the columns that define a duplicate and keep groups with HAVING COUNT(*) > 1. Join the result back to the table to see the full duplicate rows.

The grouped columns define what counts as a duplicate. NULLs group together here, and SQL Server's UNIQUE constraint agrees, permitting only one NULL because it treats NULLs as equal. That is stricter than Postgres or MySQL, so for once the GROUP BY definition and the constraint definition line up.

SELECT email, COUNT(*) AS dupes
FROM customers
GROUP BY email
HAVING COUNT(*) > 1;

See the full rows

The join brings back the full rows so you can compare them before deciding what to keep. The idiomatic SQL Server alternative is ROW_NUMBER() OVER (PARTITION BY email ORDER BY id) inside a CTE, which finds the duplicates and numbers them at once, letting you delete everything with rn > 1 directly from the CTE.

SELECT c.*
FROM customers c
JOIN (
  SELECT email
  FROM customers
  GROUP BY email
  HAVING COUNT(*) > 1
) d ON d.email = c.email
ORDER BY c.email, c.id;

Run this in SaturnSQL

SaturnSQL is a browser-based SQL editor for teams: shared query library, schema-aware autocomplete, and scheduled exports to Google Sheets and Slack.

Try it free

Related SQL Server guides