Wat is de beste manier om dubbele rijen te verwijderen uit een vrij grote SQL Server
tabel (d.w.z. 300.000+ rijen)?
De rijen zullen natuurlijk geen perfecte duplicaten zijn vanwege het bestaan van het RowID
identiteitsveld.
MijnTabel
RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null
Ervan uitgaande dat er geen nullen zijn, je GROUP BY
de unieke kolommen, en SELECT
de MIN (of MAX)
RowId als de te behouden rij. Dan, verwijder alles dat geen rij id heeft:
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
In het geval dat je een GUID hebt in plaats van een integer, kun je
MIN(RowId)
door
CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))
Er'is een goed artikel over verwijderen van duplicaten op de Microsoft Support site. Het'is vrij conservatief - ze laten je alles in afzonderlijke stappen doen - maar het zou goed moeten werken tegen grote tabellen.
Ik'heb self-joins gebruikt om dit in het verleden te doen, hoewel het waarschijnlijk kan worden opgeknapt met een HAVING-clausule:
DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField
AND dupes.secondDupField = fullTable.secondDupField
AND dupes.uniqueField > fullTable.uniqueField
Hier is nog een goed artikel over het verwijderen van duplicaten.
Het bespreekt waarom het moeilijk is: "SQL is gebaseerd op relationele algebra, en duplicaten kunnen niet voorkomen in relationele algebra, omdat duplicaten niet zijn toegestaan in een set."
De temp table oplossing, en twee mysql voorbeelden.
In de toekomst, ga je het voorkomen op database niveau, of vanuit een applicatie perspectief. Ik zou het databaseniveau voorstellen, omdat je database verantwoordelijk zou moeten zijn voor het handhaven van referentiële integriteit, ontwikkelaars zullen alleen maar problemen veroorzaken ;)