Den enkleste måde er med en CTE (common table expression). Jeg bruger denne metode, når jeg har rådata at importere; den første ting, jeg gør for at rense den, er at sikre, at der ikke er nogen dubletter --- at jeg har en slags unikt håndtag til hver række.
Oversigt:
WITH numbered AS (
SELECT ROW_NUMBER() OVER(PARTITION BY [dupe-column-list] ORDER BY [dupe-column-list]) AS _dupe_num FROM [table-name] WHERE 1=1
)
DELETE FROM numbered WHERE _dupe_num > 1;
"Dupe-column-list" delen er, hvor du angiver alle de involverede kolonner, hvor du ønsker værdier var unikke. ORDER BY er hvor du inden for et sæt af dubletter bestemmer hvilken række der "vinder", og hvilken der bliver slettet. (Den "Hvor 1=1" er kun en personlig vane.)
Grunden til, at det virker, er, at SQL Server beholder en intern, unik reference til hver kilderække, der er valgt i CTE. Så når DELETE udføres, kender den den nøjagtige række, der skal slettes, uanset hvad du sætter i din CTE's valgliste. (Hvis du er nervøs, kan du ændre "SLET" til "VÆLG *", men da du har duplikerede rækker, vil det ikke hjælpe; hvis du kunne identificere hver række entydigt, ville du ikke læse dette .)
Eksempel:
CREATE TABLE ##_dupes (col1 int, col2 int, col3 varchar(50));
INSERT INTO ##_dupes
VALUES (1, 1, 'one,one')
, (2, 2, 'two,two')
, (3, 3, 'three,three')
, (1, 1, 'one,one')
, (1, 2, 'one,two')
, (3, 3, 'three,three')
, (1, 1, 'one,one')
, (1, 2, '1,2');
Af de 8 rækker har du 5 involveret med duplikatproblemer; 3 rækker skal fjernes. Du kan se problemerne med dette:
SELECT col1
, col2
, col3
, COUNT(1) AS _total
FROM ##_dupes
WHERE 1=1
GROUP BY col1, col2, col3
HAVING COUNT(1) > 1
ORDER BY _total DESC;
Kør nu følgende forespørgsel for at fjerne dubletterne, og efterlad 1 række fra hvert sæt dubletter.
WITH numbered AS (
SELECT ROW_NUMBER() OVER(PARTITION BY col1, col2, col3 ORDER BY col1, col2, col3) AS _dupe_num FROM ##_dupes WHERE 1=1
)
DELETE FROM numbered WHERE _dupe_num > 1;
Du står nu tilbage med 5 rækker, hvoraf ingen er duplikeret.