Miten voin poistaa päällekkäiset rivit?

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
Ratkaisu

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)))
Kommentit (30)

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
Kommentit (0)

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

Kommentit (1)