Innym możliwym sposobem na to jest
;
--Ensure that any immediately preceding statement is terminated with a semicolon above
WITH cte
AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3
ORDER BY ( SELECT 0)) RN
FROM #MyTable)
DELETE FROM cte
WHERE RN > 1;
Używam ORDER BY (SELECT 0)
powyższego, ponieważ jest to dowolny wiersz, który należy zachować w przypadku remisu.
Aby zachować najnowszą RowID
, na przykład możesz użyćORDER BY RowID DESC
Plany wykonania
Plan wykonania tego jest często prostszy i wydajniejszy niż w przyjętej odpowiedzi, ponieważ nie wymaga samodzielnego dołączenia.
Jednak nie zawsze tak jest. Jednym z miejsc, w których GROUP BY
rozwiązanie może być preferowane, są sytuacje, w których agregat skrótu byłby wybierany zamiast agregatu strumienia.
ROW_NUMBER
Rozwiązanie będzie zawsze daje dość dużo ten sam plan, podczas gdy GROUP BY
strategia jest bardziej elastyczny.
Czynniki, które mogą sprzyjać podejściu agregacji skrótów, to:
- Brak przydatnego indeksu w kolumnach partycjonowania
- stosunkowo mniej grup z relatywnie większą liczbą duplikatów w każdej grupie
W skrajnych wersjach tego drugiego przypadku (jeśli jest bardzo niewiele grup z wieloma duplikatami w każdej), można również rozważyć wstawienie wierszy w celu zachowania w nowej tabeli, a następnie TRUNCATE
skopiowanie oryginału i skopiowanie ich z powrotem, aby zminimalizować rejestrowanie w porównaniu do usunięcia bardzo duża część rzędów.
DELETE FROM
bezpośrednio terminu CTE. Zobacz stackoverflow.com/q/18439054/398670