Apa cara terbaik untuk menghapus duplikat baris dari SQL Server
tabel yang cukup besar (yaitu 300.000+ baris)?
Baris, tentu saja, tidak akan menjadi duplikat yang sempurna karena keberadaan RowID
bidang identitas.
MyTable
RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null
sql-server
tsql
duplicates
Seibar
sumber
sumber
DELETE FROM
langsung menggunakan istilah CTE. Lihat stackoverflow.com/q/18439054/398670ROWID()
fungsi dengan kolom RowID, jika ada)Jawaban:
Dengan asumsi tidak ada nulls, Anda
GROUP BY
kolom yang unik, danSELECT
yangMIN (or MAX)
RowId sebagai baris untuk menjaga. Lalu, hapus saja semua yang tidak memiliki id baris:Jika Anda memiliki GUID dan bukan bilangan bulat, Anda bisa menggantinya
dengan
sumber
DELETE FROM MyTable WHERE RowId NOT IN (SELECT MIN(RowId) FROM MyTable GROUP BY Col1, Col2, Col3);
LEFT JOIN
kurang efisien daripadaNOT EXISTS
sqlinthewild.co.za/index.php/2010/03/23/... Situs yang sama juga membandingkanNOT IN
vsNOT EXISTS
. sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in Keluar dari 3 saya pikirNOT EXISTS
berkinerja terbaik. Ketiganya akan menghasilkan rencana dengan bergabung sendiri meskipun itu dapat dihindari.DELETE MyTable FROM MyTable
sintaksinya benar? Saya tidak melihat meletakkan nama tabel tepat setelahDELETE
opsi dalam dokumentasi di sini . Maaf jika ini jelas bagi orang lain; Saya seorang pemula untuk SQL hanya mencoba untuk belajar. Lebih penting daripada mengapa itu bekerja: apa perbedaan antara termasuk nama tabel di sana atau tidak?Cara lain yang memungkinkan untuk melakukan ini adalah
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 sedangkanGROUP BY
strategi lebih fleksibel.Faktor-faktor yang mungkin mendukung pendekatan agregat hash adalah
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.sumber
uniqueidentifier
. Yang ini jauh lebih sederhana dan bekerja dengan sempurna di meja mana pun. Terima kasih Martin.RowId
) untuk dibandingkan.Ada artikel bagus tentang menghapus duplikat di situs Dukungan Microsoft. Ini cukup konservatif - mereka membuat Anda melakukan semuanya dalam langkah-langkah terpisah - tetapi harus bekerja dengan baik terhadap tabel besar.
Saya telah menggunakan self-joins untuk melakukan ini di masa lalu, meskipun mungkin bisa dilengkapi dengan klausa HAVING:
sumber
Permintaan berikut berguna untuk menghapus baris duplikat. Tabel dalam contoh ini memiliki
ID
sebagai kolom identitas dan kolom yang memiliki data duplikat adalahColumn1
,Column2
danColumn3
.Penggunaan script berikut menunjukkan dari
GROUP BY
,HAVING
,ORDER BY
dalam satu query, dan kembali hasil dengan duplikat kolom dan jumlah nya.sumber
NOT IN
seringkali berkinerja lebih baik daripadaOUTER JOIN ... NULL
. Saya akan menambahkanHAVING MAX(ID) IS NOT NULL
ke permintaan meskipun meskipun semantik itu tidak perlu karena dapat meningkatkan contohPostgres:
sumber
sumber
Ini akan menghapus baris duplikat, kecuali baris pertama
Lihat ( http://www.codeproject.com/Articles/157977/Remove-Duplicate-Rows-from-a-Table-in-SQL-Server )
sumber
Saya lebih suka CTE untuk menghapus duplikat baris dari tabel sql server
sangat menyarankan untuk mengikuti artikel ini :: http://codaffection.com/sql-server-article/delete-duplicate-rows-in-sql-server/
sumber
Untuk Mengambil Baris Duplikat:
Untuk Menghapus Baris Duplikat:
sumber
DELETE FROM
, kedua, itu tidak akan berfungsi, karena Anda tidak bisaSELECT
dari tabel yang sama dengan tempat AndaDELETE
berasal. Di MySQL ini meledakMySQL error 1093
.Cepat dan Kotor untuk menghapus baris duplikat yang tepat (untuk tabel kecil):
sumber
Saya lebih suka solusi subquery \ having count (*)> 1 untuk inner join karena saya merasa lebih mudah dibaca dan sangat mudah untuk berubah menjadi pernyataan SELECT untuk memverifikasi apa yang akan dihapus sebelum Anda menjalankannya.
sumber
MAX(id)
untuk menghilangkan duplikat yang terakhir, dan ditambahkanLIMIT 1000000
ke permintaan batin sehingga tidak harus memindai seluruh tabel. Ini menunjukkan kemajuan yang jauh lebih cepat daripada jawaban lain, yang tampaknya akan bertahan berjam-jam. Setelah tabel dipangkas ke ukuran yang bisa dikelola, maka Anda bisa menyelesaikan dengan kueri lainnya. Kiat: pastikan col1 / col2 / col3 memiliki indeks untuk grup oleh.sumber
Saya pikir saya akan membagikan solusi saya karena ini bekerja dalam keadaan khusus. Saya kasus saya tabel dengan nilai duplikat tidak memiliki kunci asing (karena nilai-nilai itu digandakan dari db lain).
PS: ketika mengerjakan hal-hal seperti ini saya selalu menggunakan transaksi, ini tidak hanya memastikan semuanya dieksekusi secara keseluruhan, tetapi juga memungkinkan saya untuk menguji tanpa mempertaruhkan apapun. Tapi tentu saja Anda harus mengambil cadangan pula hanya untuk memastikan ...
sumber
Permintaan ini menunjukkan kinerja yang sangat baik untuk saya:
itu menghapus baris 1M dalam sedikit lebih dari 30detik dari tabel 2M (50% duplikat)
sumber
Menggunakan CTE. Idenya adalah untuk bergabung pada satu atau lebih kolom yang membentuk catatan duplikat dan kemudian menghapus mana yang Anda suka:
sumber
Namun solusi mudah lainnya dapat ditemukan di tautan yang ditempelkan di sini . Ini mudah dipahami dan tampaknya efektif untuk sebagian besar masalah serupa. Ini untuk SQL Server, tetapi konsep yang digunakan lebih dari dapat diterima.
Berikut adalah bagian yang relevan dari halaman yang ditautkan:
Pertimbangkan data ini:
Jadi bagaimana kita bisa menghapus data duplikat itu?
Pertama, masukkan kolom identitas dalam tabel itu dengan menggunakan kode berikut:
Gunakan kode berikut untuk mengatasinya:
sumber
ROW_NUMBER
Versi berfungsi dengan baik untuk kasus itu tanpa perlu menambahkan kolom baru sebelum Anda mulai.Berikut ini adalah artikel bagus lainnya tentang menghapus duplikat .
Ini membahas mengapa ini sulit: " SQL didasarkan pada aljabar relasional, dan duplikat tidak dapat terjadi dalam aljabar relasional, karena duplikat tidak diperbolehkan dalam satu set. "
Solusi tabel temp, dan dua contoh mysql.
Di masa depan Anda akan mencegahnya di tingkat basis data, atau dari perspektif aplikasi. Saya akan menyarankan tingkat database karena database Anda harus bertanggung jawab untuk menjaga integritas referensial, pengembang hanya akan menimbulkan masalah;)
sumber
Tentu Gunakan tabel temp. Jika Anda menginginkan pernyataan tunggal yang tidak terlalu berkinerja "berhasil", Anda dapat menggunakan:
Pada dasarnya, untuk setiap baris dalam tabel, sub-pilih menemukan RowID atas semua baris yang persis seperti baris yang dipertimbangkan. Jadi, Anda berakhir dengan daftar RowID yang mewakili baris "asli" yang tidak terduplikasi.
sumber
Saya punya meja di mana saya harus menjaga baris non-duplikat. Saya tidak yakin dengan kecepatan atau efisiensinya.
sumber
HAVING COUNT(*) > 1
?Gunakan ini
sumber
Cara lainnya adalah Buat tabel baru dengan bidang yang sama dan dengan Indeks Unik . Kemudian pindahkan semua data dari tabel lama ke tabel baru . Secara otomatis SQL SERVER abaikan (ada juga opsi tentang apa yang harus dilakukan jika akan ada nilai duplikat: abaikan, interupsi, atau sth) nilai duplikat. Jadi kami memiliki tabel yang sama tanpa baris duplikat. Jika Anda tidak ingin Indeks Unik, setelah transfer data Anda dapat menjatuhkannya .
Khusus untuk tabel yang lebih besar, Anda dapat menggunakan DTS (paket SSIS untuk mengimpor / mengekspor data) untuk mentransfer semua data dengan cepat ke tabel baru yang diindeks unik. Untuk 7 juta baris dibutuhkan hanya beberapa menit.
sumber
Dengan menggunakan kueri di bawah ini, kami dapat menghapus rekaman duplikat berdasarkan satu kolom atau beberapa kolom. kueri di bawah ini dihapus berdasarkan pada dua kolom. nama tabel adalah:
testing
dan nama kolomempno,empname
sumber
Buat tabel kosong baru dengan struktur yang sama
Jalankan query seperti ini
Kemudian jalankan query ini
sumber
Ini adalah cara termudah untuk menghapus catatan duplikat
http://askme.indianyouth.info/details/how-to-dumplicate-record-from-table-in-using-sql-105
sumber
Saya akan menyebutkan pendekatan ini juga karena dapat membantu, dan bekerja di semua server SQL: Cukup sering hanya ada satu - dua duplikat, dan Id serta jumlah duplikat dikenal. Pada kasus ini:
sumber
Saya tidak tahu seberapa baik kinerjanya, tapi saya pikir Anda bisa menulis pemicu untuk menegakkan ini, bahkan jika Anda tidak bisa melakukannya secara langsung dengan indeks. Sesuatu seperti:
Juga, varchar (2048) kedengarannya mencurigakan bagi saya (beberapa hal dalam hidup adalah 2048 bytes, tetapi sangat jarang); bukankah seharusnya itu varchar (maks)?
sumber
Cara lain untuk melakukan ini: -
sumber
sumber
sumber
Saya ingin mempratinjau baris yang akan Anda hapus dan tetap mengontrol yang mana dari baris duplikat yang akan disimpan. Lihat http://developer.azurewebsites.net/2014/09/better-sql-group-by-find-duplicate-data/
sumber