Ще один можливий спосіб цього зробити
;
--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;
Я використовую ORDER BY (SELECT 0)
вище, оскільки це довільно, який рядок потрібно зберегти у випадку зв'язання.
Щоб зберегти найновіший RowID
, щоб, наприклад, можна було його використовуватиORDER BY RowID DESC
Плани виконання
План виконання для цього часто простіший та ефективніший, ніж у прийнятій відповіді, оскільки він не вимагає самостійного приєднання.
Однак це не завжди так. Одне місце, де GROUP BY
рішення може бути кращим - це ситуації, коли хеш-агрегат вибирався б на користь потокового агрегату.
ROW_NUMBER
Рішення завжди буде давати в значній мірі той же план , тоді як GROUP BY
стратегія є більш гнучкою.
Фактори, які можуть сприяти хеш-сукупному підходу, були б
- Немає корисного індексу на стовпчиках розділів
- порівняно менше груп із відносно більшою кількістю дублікатів у кожній групі
У крайніх версіях цього другого випадку (якщо є дуже мало груп з багатьма дублікатами в кожній), можна також розглянути можливість просто вставити рядки для збереження в нову таблицю, потім TRUNCATE
- копіювання оригіналу та копіювання їх назад, щоб мінімізувати ведення журналу порівняно зі видаленням дуже висока частка рядів.
DELETE FROM
можете безпосередньо використовувати термін CTE. Дивіться stackoverflow.com/q/18439054/398670