SQL Indexing and Performance/Delete duplicate rows with a CTE

Keep one row per key and delete the extras.

Section: Data Quality and Maintenance Queries

Delete duplicate rows with a CTE

sql
sql
WITH ranked AS (
  SELECT user_id, email,
         ROW_NUMBER() OVER (PARTITION BY email ORDER BY created_at ASC) AS rn
  FROM users
)
DELETE FROM users
WHERE user_id IN (
  SELECT user_id
  FROM ranked
  WHERE rn > 1
);
Explanation

Always test duplicate-removal queries carefully before running them on production data.

Learn the surrounding workflow

Compare similar commands or jump into common fixes when this command is part of a bigger troubleshooting path.

Related commands

Same sheet · prioritizing Data Quality and Maintenance Queries
Find duplicate business keys
Detect repeated values that should be unique.
OpenIn sheetsqlsame section
Find orphaned child rows
Detect child rows missing a valid parent.
OpenIn sheetsqlsame section
Explain a query
Inspect the execution plan for a SELECT statement.
Index a common lookup column
Speed up frequent equality or range predicates.
Use keyset pagination
Paginate by a stable cursor instead of a large OFFSET.
Explain with runtime stats
Run a query and collect timing or actual row information where supported.