Hvordan kan jeg fjerne dupliserte rader?

Hva er den beste måten å fjerne dupliserte rader fra en ganske stor SQL Server-tabell (dvs. 300 000+ rader)?

Radene vil selvfølgelig ikke være perfekte duplikater på grunn av eksistensen av RowID-identitetsfeltet.

MinTabell

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

Forutsatt at det ikke er noen null, GROUP BY de unike kolonnene, og SELECT MIN (eller MAX) RowId som raden som skal beholdes. Deretter er det bare å slette alt som ikke hadde en rad-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

Hvis du har en GUID i stedet for et heltall, kan du bytte ut

MIN(RowId)

med

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

Det er en god artikkel om fjerning av duplikater på Microsoft Support-nettstedet. Det er ganske konservativt - de får deg til å gjøre alt i separate trinn - men det skal fungere bra mot store tabeller.

I've brukt self-joins for å gjøre dette i det siste, selv om det kan sannsynligvis være pyntet opp 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)

Her er en annen god artikkel om fjerning av duplikater.

Den diskuterer hvorfor det er vanskelig: "SQL er basert på relasjonsalgebra, og duplikater kan ikke forekomme i relasjonsalgebra, fordi duplikater ikke er tillatt i et sett. "

Temp-tabelløsningen, og to mysql-eksempler.

I fremtiden kommer du til å forhindre det på databasenivå, eller fra et applikasjonsperspektiv. Jeg vil foreslå databasenivået fordi databasen din skal være ansvarlig for å opprettholde referanseintegritet, utviklere vil bare forårsake problemer;)

Kommentarer (1)