Mikä on paras tapa poistaa päällekkäiset rivit melko suuresta SQL Server
-taulukosta (eli yli 300 000 riviä)?
Rivit eivät tietenkään ole täydellisiä kaksoiskappaleita, koska RowID
-identiteettikenttä on olemassa.
MyTable
RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null
Jos oletetaan, että nollia ei ole, ryhmitellään sarakkeiden perusteella ja valitaan säilytettäväksi riviksi rivin MIN (tai MAX) RowId. Poista sitten kaikki, jolla ei ollut rivin tunnusta:
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
Jos sinulla on kokonaisluvun sijasta GUID, voit korvata sen seuraavasti
MIN(RowId)
CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn)))
Microsoftin tukisivustolla on hyvä artikkeli kaksoiskappaleiden poistamisesta. Se on melko konservatiivinen - kaikki on tehtävä erillisinä vaiheina - mutta sen pitäisi toimia hyvin suuria taulukoita vastaan.
Olen aiemmin käyttänyt tähän self-joineja, vaikka sitä voitaisiinkin luultavasti kaunistella HAVING-lausekkeella:
DELETE dupes
FROM MyTable dupes, MyTable fullTable
WHERE dupes.dupField = fullTable.dupField
AND dupes.secondDupField = fullTable.secondDupField
AND dupes.uniqueField > fullTable.uniqueField
Tässä on toinen hyvä artikkeli kaksoiskappaleiden poistamisesta.
Siinä käsitellään, miksi se on vaikeaa: "SQL perustuu relaatioalgebraan, ja kaksoiskappaleet eivät voi esiintyä relaatioalgebrassa, koska kaksoiskappaleet eivät ole sallittuja joukossa."
Tempputauluratkaisu ja kaksi mysql-esimerkkiä.
Aiotko jatkossa estää sen tietokantatasolla vai sovelluksen näkökulmasta. Ehdottaisin tietokantatasoa, koska tietokantasi pitäisi olla vastuussa referentiaalisen eheyden ylläpitämisestä, kehittäjät vain aiheuttavat ongelmia ;)