Le moyen le plus simple consiste à utiliser un CTE (expression de table commune). J'utilise cette méthode lorsque j'ai des données brutes à importer; la première chose que je fais pour le nettoyer est de m'assurer qu'il n'y a pas de doublons --- que j'ai une sorte de poignée unique pour chaque ligne.
Résumé :
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;
La partie "dupe-column-list" est l'endroit où vous listez toutes les colonnes impliquées où vous souhaitez que les valeurs soient uniques. Le ORDER BY est l'endroit où vous décidez, dans un ensemble de doublons, quelle ligne "gagne" et laquelle est supprimée. (Le "WHERE 1=1" n'est qu'une habitude personnelle.)
La raison pour laquelle cela fonctionne est que SQL Server conserve une référence interne unique à chaque ligne source sélectionnée dans le CTE. Ainsi, lorsque DELETE est exécuté, il connaît la ligne exacte à supprimer, quel que soit ce que vous mettez dans la liste de sélection de votre CTE. (Si vous êtes nerveux, vous pouvez changer "SUPPRIMER" en "SELECT *", mais puisque vous avez des lignes en double, cela ne vous aidera pas ; si vous pouviez identifier chaque ligne de manière unique, vous ne liriez pas ceci .)
Exemple :
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');
Sur les 8 lignes, vous en avez 5 impliquées dans des problèmes de doublons ; 3 rangées doivent être supprimées. Vous pouvez voir les problèmes avec ceci :
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;
Exécutez maintenant la requête suivante pour supprimer les doublons, en laissant 1 ligne de chaque ensemble de doublons.
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;
Il vous reste maintenant 5 lignes, dont aucune n'est dupliquée.