Hur kan jag ta bort dubbla rader?

Vilket är det bästa sättet att ta bort dubbla rader från en ganska stor SQL Server tabell (dvs. 300 000+ rader)?

Raderna kommer naturligtvis inte att vara perfekta dubbletter eftersom identitetsfältet RowID finns.

MyTable

RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null
Lösning

Om du antar att det inte finns några nollor, så gör du en gruppering efter de unika kolumnerna och väljer den lägsta (eller högsta) RowId-numret som den rad som ska behållas. Sedan raderar du allt som inte har ett row id:

DELETE FROM MyTable
LEFT OUTER JOIN (
   SELECT MIN(RowId) as RowId, Col1, Col2, Col3 
   FROM MyTable 
   GROUP BY Col1, Col2, Col3
) as KeepRows ON
   MyTable.RowId = KeepRows.RowId
WHERE
   KeepRows.RowId IS NULL

Om du har en GUID istället för ett heltal kan du ersätta

MIN(RowId)

med

CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))
Kommentarer (30)

Det finns en bra artikel om att ta bort dubbletter på Microsofts supportwebbplats. Den är ganska konservativ - du måste göra allt i separata steg - men den borde fungera bra för stora tabeller.

Jag har tidigare använt self-joins för att göra detta, även om det förmodligen skulle kunna förbättras med en HAVING-klausul:

DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField 
AND dupes.secondDupField = fullTable.secondDupField 
AND dupes.uniqueField > fullTable.uniqueField
Kommentarer (0)

Här är en annan bra artikel om att ta bort dubbletter.

Den diskuterar varför det är svårt: "SQL bygger på relationsalgebra, och dubbletter kan inte förekomma i relationsalgebra, eftersom dubbletter inte är tillåtna i en uppsättning."

Lösningen med temp table och två mysql-exempel.

Kommer ni i framtiden att förhindra detta på databasnivå eller ur ett applikationsperspektiv? Jag skulle föreslå databasnivå eftersom din databas bör vara ansvarig för att upprätthålla referentiell integritet, utvecklare kommer bara att orsaka problem ;)

Kommentarer (1)