Cara lain yang memungkinkan untuk melakukan ini adalah
;
--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;
Saya menggunakan di ORDER BY (SELECT 0)
atas karena sewenang-wenang baris yang harus dipertahankan jika terjadi seri.
Untuk mempertahankan yang terbaru RowID
agar misalnya Anda dapat menggunakanORDER BY RowID DESC
Rencana Eksekusi
Rencana pelaksanaan untuk ini sering kali lebih sederhana dan lebih efisien daripada yang ada di jawaban yang diterima karena tidak memerlukan self join.
Namun ini tidak selalu terjadi. Satu tempat di mana GROUP BY
solusi mungkin lebih disukai adalah situasi di mana agregat hash akan dipilih dalam preferensi untuk agregat aliran.
The ROW_NUMBER
solusi akan selalu memberikan cukup banyak rencana yang sama sedangkan GROUP BY
strategi lebih fleksibel.
Faktor-faktor yang mungkin mendukung pendekatan agregat hash adalah
- Tidak ada indeks berguna pada kolom partisi
- kelompok yang relatif lebih sedikit dengan duplikat yang relatif lebih banyak di setiap kelompok
Dalam versi ekstrem dari kasus kedua ini (jika ada sangat sedikit grup dengan masing-masing duplikat di masing-masing) orang juga dapat mempertimbangkan hanya dengan memasukkan baris untuk disimpan ke dalam tabel baru kemudian TRUNCATE
-ing yang asli dan menyalinnya kembali untuk meminimalkan logging dibandingkan dengan menghapus sebuah proporsi baris yang sangat tinggi.
DELETE FROM
langsung menggunakan istilah CTE. Lihat stackoverflow.com/q/18439054/398670