Saya memiliki tabel dengan kolom varchar, dan saya ingin menemukan semua catatan yang memiliki nilai duplikat di kolom ini. Apa permintaan terbaik yang bisa saya gunakan untuk menemukan duplikat?
Karena Anda menyebutkan menemukan semua catatan, saya berasumsi Anda perlu mengetahui tombol-tombol dan juga nilai-nilai duplikat di kolom varchar itu.
TechTravelThink
Saya dapat menemukan kunci cukup mudah setelah saya mendapatkan nilai-nilai, saya benar-benar hanya ingin daftar semua nilai duplikat.
Jon Tackabury
Jawaban:
1522
Lakukan SELECTdengan GROUP BYklausa. Katakanlah nama adalah kolom yang ingin Anda temukan duplikatnya:
SELECT name, COUNT(*) c FROMtableGROUPBY name HAVING c >1;
Ini akan mengembalikan hasil dengan nilai nama di kolom pertama, dan hitungan berapa kali nilai itu muncul di kolom kedua.
Tetapi bagaimana ini berguna jika Anda tidak bisa mendapatkan ID dari baris dengan nilai duplikat? Ya, Anda dapat melakukan pencocokan kueri baru untuk setiap nilai duplikat, tetapi apakah mungkin untuk mendaftar duplikat saja?
NobleUplift
23
@NobleUplift Anda dapat melakukan GROUP_CONCAT(id)dan itu akan mencantumkan ID. Lihat jawaban saya sebagai contoh.
Matt Rardon
5
Apa artinya jika dikatakan ERROR: column "c" does not exist LINE 1?
Pengguna
15
Saya bingung mengapa ini adalah jawaban yang diterima dan mengapa ada begitu banyak upvotes. OP bertanya, "Saya ingin menemukan semua catatan yang memiliki nilai duplikat di kolom ini." Jawaban ini mengembalikan daftar jumlah. -1
Monica Heddneck
4
Bagi mereka yang tidak mengerti bagaimana HAVING bekerja - itu hanyalah sebuah filter pada set hasil, jadi terjadi setelah permintaan utama.
John Hunt
236
SELECT varchar_col
FROMtableGROUPBY varchar_col
HAVING COUNT(*)>1;
Lebih unggul daripada jawaban @ levik karena tidak menambahkan kolom tambahan. Berguna untuk digunakan dengan IN()/ NOT IN().
wmassingham
172
SELECT*FROM mytable mto
WHEREEXISTS(SELECT1FROM mytable mti
WHERE mti.varchar_column = mto.varchar_column
LIMIT 1,1)
Kueri ini mengembalikan catatan lengkap, bukan hanya berbeda varchar_column.
Kueri ini tidak digunakan COUNT(*). Jika ada banyak duplikat, COUNT(*)mahal, dan Anda tidak perlu keseluruhan COUNT(*), Anda hanya perlu tahu apakah ada dua baris dengan nilai yang sama.
Memiliki indeks atas varchar_columnkehendak, tentu saja, sangat mempercepat permintaan ini.
Baik sekali. Saya menambahkan ORDER BY varchar_column DESCke akhir permintaan.
trante
8
Ini harus menjadi jawaban yang diterima, karena GROUP BYdan HAVINGhanya mengembalikan satu dari kemungkinan duplikat. Juga, kinerja dengan bidang yang diindeks alih-alih COUNT(*), dan kemungkinan ORDER BYuntuk mengelompokkan rekaman duplikat.
Rémi Breton
1
Seperti yang dinyatakan dalam komentar di atas, kueri ini memungkinkan Anda untuk membuat daftar semua baris yang digandakan. Sangat berguna.
TryHarder
4
Melihat ini, saya tidak mengerti bagaimana cara kerjanya sama sekali. Tidakkah kondisi dalam selalu benar karena setiap baris di tabel luar juga akan tersedia di tabel dalam dan jadi setiap baris akan selalu setidaknya cocok dengan dirinya sendiri? Saya mencoba kueri dan mendapatkan hasil yang saya duga - setiap baris dikembalikan. Tetapi dengan begitu banyak upvotes saya meragukan diri saya sendiri. Bukankah permintaan dalam kehilangan sesuatu seperti "AND mto.id <> mti.id"? Ini bekerja untuk saya ketika saya menambahkannya.
Clox
2
@ Quassnoi Baiklah. Saya sudah mencoba meletakkannya di sqlfiddle tapi saya sudah menyerah karena setiap permintaan yang saya coba jalankan, selain membuat skema, waktunya akan habis. Saya mengetahui bahwa menghapus "EXISTS" juga membuat kueri berfungsi dengan benar untuk saya.
Clox
144
Membangun jawaban levik untuk mendapatkan ID dari duplikat baris yang dapat Anda lakukan GROUP_CONCATjika server Anda mendukungnya (ini akan mengembalikan daftar id yang dipisahkan koma).
SELECT GROUP_CONCAT(id), name, COUNT(*) c FROM documents GROUPBY name HAVING c >1;
Selama ini tanpa mengetahui tentang GROUP_CONCAT ()! sangat bermanfaat sekali.
Aesede
Benar-benar menghargai Matt. Ini sangat membantu! Bagi mereka yang mencoba memperbarui di phpmyadmin jika Anda membiarkan id bersama dengan fungsi seperti ini: SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]ini memungkinkan pengeditan sisip dan harus memperbarui semua baris yang terlibat (atau setidaknya yang pertama cocok), tetapi sayangnya hasil edit menghasilkan kesalahan Javascript. ..
Armfoot
Lalu bagaimana Anda menghitung berapa id yang dapat digandakan?
CMCDragonkai
2
Bagaimana saya tidak mendapatkan semua ID yang dikelompokkan, tetapi terdaftar dari pertama hingga terakhir; dengan semua nilai masing-masing di kolom di sebelahnya? Jadi alih-alih mengelompokkannya, itu hanya menunjukkan ID 1 dan nilainya, ID 2 dan nilainya. BAHKAN jika nilai untuk ID adalah sama.
MailBlade
1
Jawaban yang sangat membantu, ini harus atas sehingga lebih banyak orang melihatnya. Saya ingat betapa sakitnya saya membuat daftar seperti itu, dan itu tersedia sepanjang waktu sebagai perintah ..
John
13
Dengan asumsi tabel Anda bernama TableABC dan kolom yang Anda inginkan adalah Kol dan kunci utama untuk T1 adalah Kunci.
SELECT a.Key, b.Key, a.Col
FROM TableABC a, TableABC b
WHERE a.Col = b.Col
AND a.Key<> b.Key
Keuntungan dari pendekatan ini daripada jawaban di atas adalah memberikan Kunci.
+1 Karena berguna. Meskipun, ironisnya, hasilnya sendiri mengandung duplikat (daftar a dan b, lalu b dan a.)
Fabien Snauwaert
2
@FabienSnauwaert Anda dapat menyingkirkan beberapa duplikat dengan membandingkan kurang dari (atau lebih besar dari)
Michael
@ TechTravel. Pikirkan jawaban Anda sangat jelas, terima kasih untuk itu, tetapi pada tabel besar dibutuhkan beberapa saat (sekitar 2 juta pada lebih dari 20.000 entri tabel) dan setelah menunjukkan 25 hasil pertama, jika saya klik untuk menampilkan yang berikutnya, kesalahan acara phpmyadmin "# 1052 - Kolom 'id' dalam klausa agar tidak jelas "
bcag2
12
SELECT*FROM`dps`WHERE pid IN(SELECT pid FROM`dps`GROUPBY pid HAVING COUNT(pid)>1)
FYI - Anda akan ingin 'memilih somecol berbeda ..' jika ada potensi untuk lebih dari 1 rekaman duplikat jika tidak, hasilnya akan berisi duplikat dari baris duplikat yang ditemukan.
Drew
7
SELECT t.*,(select count(*)from city as tt
where tt.name=t.name)as count
FROM`city`as t
where(select count(*)from city as tt
where tt.name=t.name
)>1orderby count desc
Ganti kota dengan Meja Anda. Ganti nama dengan nama bidang Anda
Mengambil jawaban @ maxyfc lebih lanjut, saya perlu menemukan semua baris yang dikembalikan dengan nilai duplikat, sehingga saya bisa mengeditnya di MySQL Workbench :
SELECT*FROMtableWHERE field IN(SELECT field FROMtableGROUPBY field HAVING count(*)>1)ORDERBY field
Saya melihat hasil di atas dan permintaan akan berfungsi dengan baik jika Anda perlu memeriksa nilai kolom tunggal yang merupakan duplikat. Misalnya email.
Tetapi jika Anda perlu memeriksa dengan lebih banyak kolom dan ingin memeriksa kombinasi hasilnya, maka kueri ini akan berfungsi dengan baik:
SELECT COUNT(CONCAT(name,email))AS tot,
name,
email
FROM users
GROUPBY CONCAT(name,email)HAVING tot>1(This query will SHOW the USER list which ARE greater THAN 1AND also COUNT)
Persis apa yang dibutuhkan! Di sini pertanyaan saya, memeriksa 3 bidang untuk duplikat:SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Kai Noack
4
Saya lebih suka menggunakan fungsi berjendela (MySQL 8.0+) untuk menemukan duplikat karena saya bisa melihat seluruh baris:
WITH cte AS(SELECT*,COUNT(*)OVER(PARTITIONBY col_name)AS num_of_duplicates_group
,ROW_NUMBER()OVER(PARTITIONBY col_name ORDERBY col_name2)AS pos_in_group
FROMtable)SELECT*FROM cte
WHERE num_of_duplicates_group >1;
SELECT
t.*,(SELECT COUNT(*)FROM city AS tt WHERE tt.name=t.name)AS count
FROM`city`AS t
WHERE(SELECT count(*)FROM city AS tt WHERE tt.name=t.name)>1ORDERBY count DESC
Patut dicatat bahwa ini lambat sekali atau bahkan mungkin tidak selesai jika kolom yang ditanyakan tidak diindeks. Kalau tidak, saya bisa mengubah a.emailke a.*dan mendapatkan semua ID dari baris dengan duplikat.
NobleUplift
@NobleUplift Apa yang kamu bicarakan?
Michael
@Michael Yah karena ini adalah tiga tahun saya tidak dapat menguji pada versi MySQL apa pun yang saya gunakan, tapi saya mencoba permintaan yang sama pada database di mana kolom yang saya pilih tidak memiliki indeks di atasnya, jadi butuh cukup banyak beberapa detik untuk menyelesaikan. Mengubahnya untuk SELECT DISTINCT a.*diselesaikan hampir secara instan.
NobleUplift
@NobleUplift Ah ok. Saya dapat memahaminya karena lambat ... bagian yang saya khawatirkan adalah "bahkan mungkin tidak selesai".
Michael
@Michael Saya tidak ingat tabel mana dalam sistem kami, saya harus menjalankan kueri ini, tetapi untuk yang dengan beberapa juta catatan, mereka mungkin sudah selesai, tetapi dalam waktu yang begitu lama sehingga saya menyerah untuk melihat kapan sebenarnya akan selesai.
NobleUplift
1
Untuk menghapus duplikat baris dengan beberapa bidang, pertama-tama batal mereka ke kunci unik baru yang ditentukan untuk satu-satunya baris yang berbeda, kemudian gunakan perintah "grup dengan" untuk menghapus baris duplikat dengan kunci unik baru yang sama:
Create TEMPORARY table tmp select concat(f1,f2)as cfs,t1.*from mytable as t1;Createindex x_tmp_cfs on tmp(cfs);Createtable unduptable select f1,f2,...from tmp groupby cfs;
Kenapa tidak digunakan CREATE TEMPORARY TABLE ...? Sedikit penjelasan tentang solusi Anda akan sangat bagus.
maxhb
1
Satu kontribusi yang sangat terlambat ... kalau-kalau ada orang yang membantu ... Saya punya tugas untuk menemukan pasangan transaksi yang cocok (sebenarnya kedua sisi transfer antar-akun) dalam aplikasi perbankan, untuk mengidentifikasi mana yang adalah 'dari' dan 'ke' untuk setiap transaksi antar rekening, jadi kami berakhir dengan ini:
SELECT
LEAST(primaryid, secondaryid)AS transactionid1,
GREATEST(primaryid, secondaryid)AS transactionid2
FROM(SELECT table1.transactionid AS primaryid,
table2.transactionid AS secondaryid
FROM financial_transactions table1
INNERJOIN financial_transactions table2
ON table1.accountid = table2.accountid
AND table1.transactionid <> table2.transactionid
AND table1.transactiondate = table2.transactiondate
AND table1.sourceref = table2.destinationref
AND table1.amount =(0- table2.amount))AS DuplicateResultsTable
GROUPBY transactionid1
ORDERBY transactionid1;
Hasilnya adalah bahwa DuplicateResultsTablemenyediakan baris yang berisi transaksi yang cocok (yaitu duplikat), tetapi juga memberikan id transaksi yang sama secara terbalik saat kedua cocok dengan pasangan yang sama, sehingga bagian luar SELECTada untuk dikelompokkan berdasarkan ID transaksi pertama, yang dilakukan dengan menggunakan LEASTdan GREATESTmemastikan kedua transaksi itu selalu dalam urutan yang sama dalam hasil, yang membuatnya aman untuk GROUPyang pertama, sehingga menghilangkan semua kecocokan duplikat. Telusuri hampir satu juta catatan dan identifikasi 12.000+ pertandingan hanya dalam waktu kurang dari 2 detik. Tentu saja transactionid adalah indeks utama, yang sangat membantu.
Jawaban:
Lakukan
SELECT
denganGROUP BY
klausa. Katakanlah nama adalah kolom yang ingin Anda temukan duplikatnya:Ini akan mengembalikan hasil dengan nilai nama di kolom pertama, dan hitungan berapa kali nilai itu muncul di kolom kedua.
sumber
GROUP_CONCAT(id)
dan itu akan mencantumkan ID. Lihat jawaban saya sebagai contoh.ERROR: column "c" does not exist LINE 1
?sumber
IN()
/NOT IN()
.Kueri ini mengembalikan catatan lengkap, bukan hanya berbeda
varchar_column
.Kueri ini tidak digunakan
COUNT(*)
. Jika ada banyak duplikat,COUNT(*)
mahal, dan Anda tidak perlu keseluruhanCOUNT(*)
, Anda hanya perlu tahu apakah ada dua baris dengan nilai yang sama.Memiliki indeks atas
varchar_column
kehendak, tentu saja, sangat mempercepat permintaan ini.sumber
ORDER BY varchar_column DESC
ke akhir permintaan.GROUP BY
danHAVING
hanya mengembalikan satu dari kemungkinan duplikat. Juga, kinerja dengan bidang yang diindeks alih-alihCOUNT(*)
, dan kemungkinanORDER BY
untuk mengelompokkan rekaman duplikat.Membangun jawaban levik untuk mendapatkan ID dari duplikat baris yang dapat Anda lakukan
GROUP_CONCAT
jika server Anda mendukungnya (ini akan mengembalikan daftar id yang dipisahkan koma).sumber
SELECT id, GROUP_CONCAT(id), name, COUNT(*) c [...]
ini memungkinkan pengeditan sisip dan harus memperbarui semua baris yang terlibat (atau setidaknya yang pertama cocok), tetapi sayangnya hasil edit menghasilkan kesalahan Javascript. ..Dengan asumsi tabel Anda bernama TableABC dan kolom yang Anda inginkan adalah Kol dan kunci utama untuk T1 adalah Kunci.
Keuntungan dari pendekatan ini daripada jawaban di atas adalah memberikan Kunci.
sumber
sumber
Untuk menemukan berapa banyak rekaman duplikat di kolom nama di Karyawan, pertanyaan di bawah ini sangat membantu;
sumber
untuk mendapatkan semua data yang mengandung duplikasi saya menggunakan ini:
TableName = tabel yang Anda kerjakan.
DupliactedData = data duplikat yang Anda cari.
sumber
Kueri terakhir saya memasukkan beberapa jawaban di sini yang membantu - menggabungkan grup dengan, menghitung & GROUP_CONCAT.
Ini memberikan id dari kedua contoh (dipisahkan koma), barcode yang saya butuhkan, dan berapa banyak duplikat.
Ubah tabel dan kolom sesuai kebutuhan.
sumber
Saya tidak melihat pendekatan GABUNG, yang memiliki banyak kegunaan dalam hal duplikat.
Pendekatan ini memberi Anda hasil berlipat ganda yang sebenarnya.
sumber
Ganti kota dengan Meja Anda. Ganti nama dengan nama bidang Anda
sumber
Mengambil jawaban @ maxyfc lebih lanjut, saya perlu menemukan semua baris yang dikembalikan dengan nilai duplikat, sehingga saya bisa mengeditnya di MySQL Workbench :
sumber
Saya melihat hasil di atas dan permintaan akan berfungsi dengan baik jika Anda perlu memeriksa nilai kolom tunggal yang merupakan duplikat. Misalnya email.
Tetapi jika Anda perlu memeriksa dengan lebih banyak kolom dan ingin memeriksa kombinasi hasilnya, maka kueri ini akan berfungsi dengan baik:
sumber
SELECT COUNT(CONCAT(userid,event,datetime)) AS total, userid, event, datetime FROM mytable GROUP BY CONCAT(userid, event, datetime ) HAVING total>1
Saya lebih suka menggunakan fungsi berjendela (MySQL 8.0+) untuk menemukan duplikat karena saya bisa melihat seluruh baris:
DB Fiddle Demo
sumber
sumber
Berikut ini akan menemukan semua product_id yang digunakan lebih dari sekali. Anda hanya mendapatkan satu catatan untuk setiap product_id.
Kode diambil dari: http://chandreshrana.blogspot.in/2014/12/find-duplicate-records-based-on-any.html
sumber
sumber
sumber
a.email
kea.*
dan mendapatkan semua ID dari baris dengan duplikat.SELECT DISTINCT a.*
diselesaikan hampir secara instan.Untuk menghapus duplikat baris dengan beberapa bidang, pertama-tama batal mereka ke kunci unik baru yang ditentukan untuk satu-satunya baris yang berbeda, kemudian gunakan perintah "grup dengan" untuk menghapus baris duplikat dengan kunci unik baru yang sama:
sumber
CREATE TEMPORARY TABLE ...
? Sedikit penjelasan tentang solusi Anda akan sangat bagus.Satu kontribusi yang sangat terlambat ... kalau-kalau ada orang yang membantu ... Saya punya tugas untuk menemukan pasangan transaksi yang cocok (sebenarnya kedua sisi transfer antar-akun) dalam aplikasi perbankan, untuk mengidentifikasi mana yang adalah 'dari' dan 'ke' untuk setiap transaksi antar rekening, jadi kami berakhir dengan ini:
Hasilnya adalah bahwa
DuplicateResultsTable
menyediakan baris yang berisi transaksi yang cocok (yaitu duplikat), tetapi juga memberikan id transaksi yang sama secara terbalik saat kedua cocok dengan pasangan yang sama, sehingga bagian luarSELECT
ada untuk dikelompokkan berdasarkan ID transaksi pertama, yang dilakukan dengan menggunakanLEAST
danGREATEST
memastikan kedua transaksi itu selalu dalam urutan yang sama dalam hasil, yang membuatnya aman untukGROUP
yang pertama, sehingga menghilangkan semua kecocokan duplikat. Telusuri hampir satu juta catatan dan identifikasi 12.000+ pertandingan hanya dalam waktu kurang dari 2 detik. Tentu saja transactionid adalah indeks utama, yang sangat membantu.sumber
sumber
sumber
Jika Anda ingin menghapus penggunaan duplikat
DISTINCT
Kalau tidak gunakan pertanyaan ini:
SELECT users.*,COUNT(user_ID) as user FROM users GROUP BY user_name HAVING user > 1;
sumber
Coba gunakan permintaan ini:
sumber