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
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)))
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
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;)