Qual è il modo migliore per rimuovere le righe duplicate da una tabella SQL Server
abbastanza grande (cioè 300.000+ righe)?
Le righe, ovviamente, non saranno duplicati perfetti a causa dell'esistenza del campo di identità RowID
.
MyTable
RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null
Supponendo che non ci siano null, si GROUP BY
le colonne uniche, e SELECT
il MIN (o MAX)
RowId come riga da mantenere. Poi, cancella semplicemente tutto ciò che non ha un id di riga:
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
Nel caso tu abbia un GUID invece di un intero, puoi sostituire
MIN(RowId)
con
CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))
C'è un buon articolo sulla rimozione dei duplicati sul sito del supporto Microsoft. È piuttosto conservativo - ti fanno fare tutto in passi separati - ma dovrebbe funzionare bene con tabelle grandi.
Ho usato self-join per fare questo in passato, anche se probabilmente potrebbe essere migliorato con una clausola HAVING:
DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField
AND dupes.secondDupField = fullTable.secondDupField
AND dupes.uniqueField > fullTable.uniqueField
Ecco un altro buon articolo sulla rimozione dei duplicati.
Discute perché è difficile: "SQL è basato sull'algebra relazionale, e i duplicati non possono verificarsi nell'algebra relazionale, perché i duplicati non sono ammessi in un insieme."
La soluzione della tabella temporanea e due esempi di mysql.
In futuro hai intenzione di prevenirlo a livello di database o dal punto di vista dell'applicazione. Suggerirei il livello del database perché il tuo database dovrebbe essere responsabile del mantenimento dell'integrità referenziale, gli sviluppatori causeranno solo problemi ;)