how to delete duplicate records from table.
ssprastogi 0 Newbie Poster
Dani AI
Generated
Thread already shows two common options: posted a join-based delete and demonstrated ROW_NUMBER() with a temp table. The concise, safe pattern below uses a CTE so a single statement removes duplicates in SQL Server 2005+ without a separate temp table, and is followed by practical operational tips that are frequently missing from simple examples.
WITH Duplicates AS (
SELECT
id,
ROW_NUMBER() OVER (PARTITION BY ColA, ColB ORDER BY id) AS rn
FROM dbo.MyTable
)
DELETE FROM Duplicates
WHERE rn > 1; This keeps one row per ColA/ColB group (the row with the lowest id). Change the ORDER BY to keep the newest/oldest row as required.
Operational checklist and cautions:
- Preview first: run the CTE as a SELECT to confirm which ids will be removed.
- Protect production data: back up or run inside an explicit transaction/savepoint so the operation can be rolled back.
- Referential integrity: check foreign keys, cascades, and triggers. If other tables point to the rows being removed, consolidate or update those references before deleting to avoid orphaned FK relationships.
- Large tables: avoid single massive transactions. Delete in manageable batches (DELETE TOP (N) in a loop and check @@ROWCOUNT) to limit log growth and lock escalation. Drop or disable nonclustered indexes before huge deletes and rebuild them afterward if appropriate.
- Prevent recurrence: after cleanup, create a UNIQUE constraint or unique index on the de-duplication columns to enforce the rule going forward.
This complements and by providing the direct CTE-delete pattern plus the real-world steps needed for safe, performant cleanup in production environments.
Recommended Answers
Jump to Post— aboyd 1DELETE FROM table1 USING table1, table1 AS vtable WHERE (table1.ID > vtable.ID) AND (table1.field_name=vtable.field_name)You may need to have lots of ANDs at the end, if you want lots of fields to be the same. If you just want to delete records that have ONE field the …
All 2 Replies
aboyd 1 Junior Poster in Training
DELETE FROM table1
USING table1, table1 AS vtable
WHERE (table1.ID > vtable.ID)
AND (table1.field_name=vtable.field_name) You may need to have lots of ANDs at the end, if you want lots of fields to be the same. If you just want to delete records that have ONE field the same, then my example works already.
As an example, let's adapt the SQL above to remove records from a table called macintosh. The table has many columns, but we're going to call a record a duplicate if three (of the many) columns match. Here we go:
DELETE FROM macintosh
USING macintosh, macintosh AS m2
WHERE (macintosh.id > m2.id)
AND (macintosh.manufacturer=m2.manufacturer)
AND (macintosh.model=m2.model)
AND (macintosh.os=m2.os) PLEASE only try this on a copy of your database table. Do not run this on production tables until you've certified that it works.
cmhampton 8 Junior Poster in Training
If you are using SQL 2005, here's another option. (originally posted in http://www.daniweb.com/forums/post639423-7.html)
Suppose you have a table with the following structure:
id - int PrimaryKey
name - varchar(50)
description - varchar(MAX) and the following values:
1 Joe Short for Joseph
2 Dave Short for David
3 Joe Short for Joseph
4 Joe Short for Joseph
5 Chris Short for Christian
6 Rob Short for Robert Notice that "Joe - Short for Joseph" has three duplicate records. It is true that we can use SELECT DISTINCT to filter these, and for a simple table like this, that's probably the best option. However, sometimes SELECT DISTINCT gets a little hairy when dealing with joins, at least in my experience. So, without having the time to create a complex data structure, or using one I already have that contains confidential data, let's use this simple example.
MSSQL 2005 added a handy new function called ROW_NUMBER(). Learn it, love it (lol). Seriously though, it will make your life easier. What this function does is allow you to get the row number of a record in a returned data table. On the surface, this doesn't sound like much. But, it becomes extremely useful when you realize that you can partition, or group, the records. Let use this on the table shown above:
WITH names AS
(
SELECT
id,
name,
description,
ROW_NUMBER() OVER(PARTITION BY name, description ORDER BY id) AS rowNum
FROM
table_1
)
SELECT
id,
name,
description,
rowNum
FROM
names We get these results:
id name description rowNum
5 Chris Short for Christian 1
2 Dave Short for David 1
1 Joe Short for Joseph 1
3 Joe Short for Joseph 2
4 Joe Short for Joseph 3
6 Rob Short for Robert 1 Notice that now we have rowNumbers for each record, and they are partitioned by the name and description fields. So, if we want to get the duplicate records for this table, we add a WHERE clause to the query:
SELECT
id,
name,
description
FROM
names
WHERE
rowNum > 1 which gives us:
3 Joe Short for Joseph 2
4 Joe Short for Joseph 3 Cool isn't it?
What this allows us to do, is dump this into a temporary table to use as in a subquery...
DECLARE @tblNames TABLE(id int);
WITH names AS
(
SELECT
id,
name,
description,
ROW_NUMBER() OVER(PARTITION BY name, description ORDER BY id) AS rowNum
FROM
table_1
)
INSERT
@tblNames
SELECT
id
FROM
names
WHERE
rowNum > 1
DELETE
FROM
table_1
WHERE
id IN
(
SELECT
id
FROM
@tblNames
) Now if we select the records from table_1, the duplicates have been eliminated. Here's the results:
1 Joe Short for Joseph
2 Dave Short for David
5 Chris Short for Christian
6 Rob Short for Robert There's a way to do this without the temp table, but I can't find my original query, so I had to do it from memory.
Sorry to turn this into a novel, but I thought an explanation would be better than a code dump.
Be a part of the DaniWeb community
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.