Najprostszym sposobem jest CTE (wspólne wyrażenie tabelowe). Używam tej metody, gdy mam surowe dane do zaimportowania; pierwszą rzeczą, którą robię, aby go oczyścić, jest upewnienie się, że nie ma duplikatów — że mam jakiś unikalny uchwyt do każdego wiersza.
Podsumowanie:
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;
Część „dupe-column-list” to miejsce, w którym wymieniasz wszystkie zaangażowane kolumny, w których chcesz, aby wartości były unikatowe. ORDER BY to miejsce, w którym decydujesz, w zestawie duplikatów, który wiersz „wygrywa”, a który zostanie usunięty. ("WHERE 1=1" to tylko osobisty nawyk).
Powodem, dla którego to działa, jest to, że SQL Server przechowuje wewnętrzne, unikalne odniesienie do każdego wiersza źródłowego wybranego w CTE. Więc kiedy DELETE jest wykonywane, wie dokładnie, który wiersz ma zostać usunięty, niezależnie od tego, co umieścisz na liście wyboru CTE. (Jeśli jesteś zdenerwowany, możesz zmienić „USUŃ” na „WYBIERZ *”, ale ponieważ masz zduplikowane wiersze, to nie pomoże; gdybyś mógł jednoznacznie zidentyfikować każdy wiersz, nie czytałbyś tego .)
Przykład:
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');
Spośród 8 wierszy masz 5 związanych z powtarzającymi się problemami; Należy usunąć 3 rzędy. Możesz zobaczyć problemy z tym:
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;
Teraz uruchom następujące zapytanie, aby usunąć duplikaty, pozostawiając 1 wiersz z każdego zestawu duplikatów.
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;
Masz teraz 5 wierszy, z których żaden nie jest zduplikowany.