Bagaimana cara menghapus duplikat pada tabel MySQL?


158

Saya perlu DELETEmenduplikasi baris untuk sid yang ditentukan di atas MySQLmeja.

Bagaimana saya bisa melakukan ini dengan query SQL?

DELETE (DUPLICATED TITLES) FROM table WHERE SID = "1"

Sesuatu seperti ini, tetapi saya tidak tahu bagaimana melakukannya.


Apakah Anda hanya perlu melakukannya sekali atau Anda perlu melakukannya sepanjang waktu?
Billy ONeal

Apakah catatan dengan catatan duplikat semua memiliki data yang sama, atau apakah bidang lainnya berbeda satu sama lain? Jika Anda memiliki opsi pertama, Anda bisa menghapus semua catatan kecuali satu, jika Anda memiliki opsi kedua, bagaimana Anda menentukan catatan mana yang ingin Anda simpan?
rael_kid

@Lex Opsi pertama. @Illy saya harus melakukannya sepanjang waktu.
Ali Demirci

1
kemungkinan duplikat Hapus baris duplikat di MySQL
Basilevs

1
Ada banyak hal yang berubah di sini dalam berbagai versi MySQL. Periksa versi MySQL Anda dengan saksama sebelum melangkah keluar dari salah satu solusi di sini.
delatbabel

Jawaban:


215

ini menghapus duplikat di tempatnya, tanpa membuat tabel baru

ALTER IGNORE TABLE `table_name` ADD UNIQUE (title, SID)

Catatan: hanya berfungsi dengan baik jika indeks sesuai dalam memori


26
Perhatikan: ini akan menyimpan catatan duplikat terlama dan akan menghapus yang lebih baru. Jika Anda ingin menyimpan yang terbaru, Anda tidak dapat melakukannya ALTER IGNORE.
Haralan Dobrev

9
Tampaknya tidak berfungsi dengan InnoDB. Saya berlari ALTER TABLE foo ENGINE MyISAMuntuk mengatasinya, mengganti mesin kembali setelah.
Martin

13
ini mungkin gagal pada MySQL> 5.5, jika demikian gunakan "set session old_alter_table = 1;" dan "setel sesi old_alter_table = 0;" sebelum dan sesudah pernyataan
chillitom


2
@delatbabel Alasan mencabutnya diberikan pada halaman yang Anda tautkan.
Barmar

133

Misalkan Anda memiliki tabel employee, dengan kolom berikut:

employee (first_name, last_name, start_date)

Untuk menghapus baris dengan first_namekolom duplikat :

delete
from employee using employee,
    employee e1
where employee.id > e1.id
    and employee.first_name = e1.first_name  

1
Catatan yang tersisa akan memiliki id maksimum atau minimum dalam grup duplikatnya?
Api Beku

Catatan yang tersisa akan memiliki id minimum karena itu adalah satu-satunya yang tidak memenuhi syarat untuk dihapus
Pablo Guerrero

1
Sepertinya bergabung employeemelawan dirinya sendiri untuk satu pertandingan indeks dan satu >pemeriksaan indeks akan lambat untuk tabel besar. Bukankah lebih baik SELECT MAX(ID) FROM t GROUP BY uniquedan kemudian JOINdengan kecocokan persis IDke MAX(ID)?
ebyrob

1
Jawaban bagus! Menghemat waktu saya!
Nesar

56

Mengikuti menghapus duplikat untuk semua SID-s, tidak hanya satu.

Dengan meja temp

CREATE TABLE table_temp AS
SELECT * FROM table GROUP BY title, SID;

DROP TABLE table;
RENAME TABLE table_temp TO table;

Sejak temp_table baru dibuat tidak memiliki indeks. Anda harus membuatnya ulang setelah menghapus duplikat. Anda dapat memeriksa indeks apa yang Anda miliki di tabelSHOW INDEXES IN table

Tanpa tabel temp:

DELETE FROM `table` WHERE id IN (
  SELECT all_duplicates.id FROM (
    SELECT id FROM `table` WHERE (`title`, `SID`) IN (
      SELECT `title`, `SID` FROM `table` GROUP BY `title`, `SID` having count(*) > 1
    )
  ) AS all_duplicates 
  LEFT JOIN (
    SELECT id FROM `table` GROUP BY `title`, `SID` having count(*) > 1
  ) AS grouped_duplicates 
  ON all_duplicates.id = grouped_duplicates.id 
  WHERE grouped_duplicates.id IS NULL
)

4
KELOMPOK menghasilkan hanya satu baris hasil untuk setiap kombinasi nilai bidang yang Anda kelompokkan. Jadi duplikat akan dihapus.
Kamil Szot

4
Saya suka cara pertama, terlalu elegan di sini! : B
AgelessEssence

1
@fiacre Anda dapat menonaktifkan pemeriksaan kunci asing untuk sementara: stackoverflow.com/questions/15501673/... Anda juga bisa berisiko menghapus beberapa baris yang dirujuk oleh tabel lain, tetapi Anda bisa mengontrol catatan mana yang diambil ke tabel yang dikurangi dengan mengubah kueri SELECT * FROM table GROUP BY title, SID;Itu semua tergantung pada seberapa baik Anda tahu apa yang Anda lakukan.
Kamil Szot

1
@ ahnbizcad Anda bisa menggunakan tabel sementara tetapi kemudian Anda harus menyalin data kembali dari tabel sementara ke tabel biasa. Jika Anda menggunakan tabel nyata, Anda bisa menjatuhkan yang lama dengan duplikat dan mengganti nama yang baru, tanpa duplikat ke nama yang lama.
Kamil Szot

1
Metode "tanpa tabel temp" adalah yang paling dekat dengan solusi terbaik namun waspadalah terhadap penanganan ONLY_FULL_GROUP_BY yang berubah di MySQL 5.7.5: dev.mysql.com/doc/refman/5.7/en/group-by-handling.html Saya dapat ini untuk bekerja dengan mengganti "SELECT id" dengan "SELECT ANY_VALUE (id) AS id"
delatbabel

53

Menghapus baris duplikat di MySQL di tempat, (Asumsikan Anda memiliki timestamp col untuk diurutkan berdasarkan) panduan:

Buat tabel dan masukkan beberapa baris:

create table penguins(foo int, bar varchar(15), baz datetime);
insert into penguins values(1, 'skipper', now());
insert into penguins values(1, 'skipper', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(3, 'kowalski', now());
insert into penguins values(4, 'rico', now());
select * from penguins;
    +------+----------+---------------------+
    | foo  | bar      | baz                 |
    +------+----------+---------------------+
    |    1 | skipper  | 2014-08-25 14:21:54 |
    |    1 | skipper  | 2014-08-25 14:21:59 |
    |    3 | kowalski | 2014-08-25 14:22:09 |
    |    3 | kowalski | 2014-08-25 14:22:13 |
    |    3 | kowalski | 2014-08-25 14:22:15 |
    |    4 | rico     | 2014-08-25 14:22:22 |
    +------+----------+---------------------+
6 rows in set (0.00 sec)

Hapus duplikat di tempat:

delete a
    from penguins a
    left join(
    select max(baz) maxtimestamp, foo, bar
    from penguins
    group by foo, bar) b
    on a.baz = maxtimestamp and
    a.foo = b.foo and
    a.bar = b.bar
    where b.maxtimestamp IS NULL;
Query OK, 3 rows affected (0.01 sec)
select * from penguins;
+------+----------+---------------------+
| foo  | bar      | baz                 |
+------+----------+---------------------+
|    1 | skipper  | 2014-08-25 14:21:59 |
|    3 | kowalski | 2014-08-25 14:22:15 |
|    4 | rico     | 2014-08-25 14:22:22 |
+------+----------+---------------------+
3 rows in set (0.00 sec)

Anda selesai, baris duplikat dihapus, yang terakhir dengan stempel waktu disimpan.

Bagi Anda tanpa stempel waktu atau kolom unik.

Anda tidak punya timestamp kolom indeks unik atau untuk disortir? Anda hidup dalam kondisi degenerasi. Anda harus melakukan langkah-langkah tambahan untuk menghapus baris duplikat.

buat tabel penguin dan tambahkan beberapa baris

create table penguins(foo int, bar varchar(15)); 
insert into penguins values(1, 'skipper'); 
insert into penguins values(1, 'skipper'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(3, 'kowalski'); 
insert into penguins values(4, 'rico'); 
select * from penguins; 
    # +------+----------+ 
    # | foo  | bar      | 
    # +------+----------+ 
    # |    1 | skipper  | 
    # |    1 | skipper  | 
    # |    3 | kowalski | 
    # |    3 | kowalski | 
    # |    3 | kowalski | 
    # |    4 | rico     | 
    # +------+----------+ 

buat klon dari tabel pertama dan salin ke dalamnya.

drop table if exists penguins_copy; 
create table penguins_copy as ( SELECT foo, bar FROM penguins );  

#add an autoincrementing primary key: 
ALTER TABLE penguins_copy ADD moo int AUTO_INCREMENT PRIMARY KEY first; 

select * from penguins_copy; 
    # +-----+------+----------+ 
    # | moo | foo  | bar      | 
    # +-----+------+----------+ 
    # |   1 |    1 | skipper  | 
    # |   2 |    1 | skipper  | 
    # |   3 |    3 | kowalski | 
    # |   4 |    3 | kowalski | 
    # |   5 |    3 | kowalski | 
    # |   6 |    4 | rico     | 
    # +-----+------+----------+ 

Agregat maks beroperasi pada indeks moo baru:

delete a from penguins_copy a left join( 
    select max(moo) myindex, foo, bar 
    from penguins_copy 
    group by foo, bar) b 
    on a.moo = b.myindex and 
    a.foo = b.foo and 
    a.bar = b.bar 
    where b.myindex IS NULL; 

#drop the extra column on the copied table 
alter table penguins_copy drop moo; 
select * from penguins_copy; 

#drop the first table and put the copy table back: 
drop table penguins; 
create table penguins select * from penguins_copy; 

amati dan bersihkan

drop table penguins_copy; 
select * from penguins;
+------+----------+ 
| foo  | bar      | 
+------+----------+ 
|    1 | skipper  | 
|    3 | kowalski | 
|    4 | rico     | 
+------+----------+ 
    Elapsed: 1458.359 milliseconds 

Apa yang dilakukan pernyataan penghapusan SQL besar itu?

Penguin tabel dengan alias 'a' dibiarkan bergabung pada subset penguin tabel yang disebut alias 'b'. Tabel kanan 'b' yang merupakan himpunan bagian menemukan timestamp max [atau maks moo] dikelompokkan berdasarkan kolom foo dan bar. Ini cocok dengan tabel sebelah kiri 'a'. (foo, bar, baz) di sebelah kiri memiliki setiap baris di tabel. Subset kanan 'b' memiliki (maxtimestamp, foo, bar) yang dicocokkan dengan kiri hanya pada yang memiliki maks.

Setiap baris yang bukan berarti max memiliki nilai maxtimestamp dari NULL. Saring ke bawah pada baris NULL tersebut dan Anda memiliki satu set semua baris yang dikelompokkan berdasarkan foo dan bar yang bukan cap timestamp terbaru. Hapus yang itu.

Buat cadangan tabel sebelum Anda menjalankan ini.

Cegah agar masalah ini tidak terjadi lagi di tabel ini:

Jika Anda berhasil, dan ini memadamkan "duplikat baris" Anda. Bagus. Sekarang tentukan kunci unik komposit baru pada tabel Anda (pada dua kolom itu) untuk mencegah duplikat ditambahkan dari awal.

Seperti sistem kekebalan yang baik, baris-baris yang buruk seharusnya tidak diperbolehkan masuk ke meja pada saat dimasukkan. Nanti semua program yang menambahkan duplikat akan menyiarkan protes mereka, dan ketika Anda memperbaikinya, masalah ini tidak pernah muncul lagi.


6
tingkat murni untuk referensi Madagaskar!
Michael Wiggins

1
Dinilai tinggi karena ini adalah jawaban yang bagus, dan saran yang bagus, terima kasih Eric bekerja lebih baik daripada jawaban lain di luar sana.
johan

4
Catatan: Jika tabel Anda memiliki IDkolom kenaikan otomatis maka ONklausa hanya perlu cocok dengan IDkolom, tidak ada yang lain.
ebyrob

1
Saya suka penjelasan terperinci tapi ... Jika saya mengerti dengan benar, jawaban ini menggunakan cap waktu untuk membedakan antara catatan. Dalam hal itu, catatan tidak duplikat. Bagaimana jika Anda tidak memiliki cap waktu untuk membedakan antara catatan yaitu semua cols sama untuk 2 atau lebih catatan?
Rsc Rsc

1
@RscRsc Jika Anda tidak memiliki kolom stempel waktu atau indeks unik untuk menerapkan agregat maksimum untuk maka sepertinya Anda harus menduplikasi tabel, tambahkan indeks unik, terapkan pernyataan hapus, kemudian gantilah tabel yang di-coped kembali ke aslinya . Saya mengubah jawaban untuk mencerminkan instruksi ini.
Eric Leschinski

16

Setelah mengalami sendiri masalah ini, pada basis data yang sangat besar, saya tidak sepenuhnya terkesan dengan kinerja dari jawaban yang lain. Saya hanya ingin menyimpan baris duplikat terbaru, dan menghapus sisanya.

Dalam pernyataan satu-permintaan, tanpa tabel temp, ini bekerja paling baik untuk saya,

DELETE e.*
FROM employee e
WHERE id IN
 (SELECT id
   FROM (SELECT MIN(id) as id
          FROM employee e2
          GROUP BY first_name, last_name
          HAVING COUNT(*) > 1) x);

Satu-satunya peringatan adalah bahwa saya harus menjalankan kueri beberapa kali, tetapi bahkan dengan itu, saya menemukan itu bekerja lebih baik untuk saya daripada opsi lainnya.


1
Solusi pragmatis! Bekerja untuk saya - sekitar 20-an untuk tabel innodb 2m + baris. Setelah saya menggunakannya beberapa kali dan turun ke beberapa pelaku dengan jumlah duplikat yang tinggi, menyelesaikan pekerjaan secara manual.
Troy Wray

1
Bekerja untuk saya dalam satu sapuan, luar biasa!
Murwa

Ini harus dijalankan beberapa kali jika duplikat untuk kolom lebih dari 2x
PayteR

@PayteR yang dinyatakan dalam jawaban, "Satu-satunya peringatan adalah bahwa saya harus menjalankan kueri beberapa kali"
seaders

13

Ini sepertinya selalu berhasil bagi saya:

CREATE TABLE NoDupeTable LIKE DupeTable; 
INSERT NoDupeTable SELECT * FROM DupeTable group by CommonField1,CommonFieldN;

Yang menyimpan ID terendah pada masing-masing dupes dan sisa catatan non-dupe.

Saya juga harus melakukan yang berikut sehingga masalah dupe tidak lagi terjadi setelah penghapusan:

CREATE TABLE NoDupeTable LIKE DupeTable; 
Alter table NoDupeTable Add Unique `Unique` (CommonField1,CommonField2);
INSERT IGNORE NoDupeTable SELECT * FROM DupeTable;

Dengan kata lain, saya membuat duplikat dari tabel pertama, menambahkan indeks unik pada bidang yang saya tidak ingin duplikat, dan kemudian melakukan Insert IGNOREyang memiliki keuntungan tidak gagal seperti biasaInsert akan pertama kali mencoba menambahkan catatan duplikat berdasarkan dua bidang dan lebih baik mengabaikan catatan tersebut.

Memindahkan fwd menjadi tidak mungkin untuk membuat rekaman duplikat berdasarkan kedua bidang tersebut.


1
Tidakkah Anda membutuhkan ORDER BYjawaban SELECTuntuk memastikan rekaman mana yang benar-benar membuatnya NoDupeTable?
ebyrob

@ebyrob Saya percaya kecuali diperintahkan sebaliknya akan memilih ID terendah tanpa adanya kriteria lain. Tentu saja ORDER by ID Asctidak ada salahnya, jadi saya akan mengedit jawaban saya tanpa masalah.
user3649739

@ebyrob Maaf, salahku. Pesanan oleh tidak akan berfungsi dalam pilih ini untuk pengetahuan saya. Pesanan pada akhir pilih hanya akan memesan duplikat yang ditemukan oleh ID terendah yang ditemukan di setiap pasangan. Bergantian Anda bisa melakukan Select Max(ID)dan kemudian Order by Max(ID)tetapi semua yang akan dilakukan adalah membalik urutan insert. Untuk mengambil ID tertinggi akan dibutuhkan, saya yakin pilih join yang lebih kompleks, terlepas dari bagaimana Anda memesan di atas, Anda akan mengambil nilai field dari ID yang lebih rendah.
user3649739

Sebenarnya, tidak yakin apa yang saya pikirkan dengan pesanan. Anda pasti ingin MAX(ID)atau MIN(ID)dan nama kolom daripada *di SELECT FROM DupeTableolah, kalau tidak, Anda hanya akan mendapatkan salah satu dari IDitu secara acak. Faktanya, banyak SQL dan bahkan MySQL yang ketat mengharuskan pemanggilan fungsi agregat pada setiap kolom yang tidak ditentukan dalam GROUP BYklausa.
ebyrob

@ebyrob Pada pengujian Max (ID) Min (ID) tidak melakukan apa pun kecuali mengembalikan ID dari catatan Max atau Mind. Dalam setiap kasus, ambil catatan yang sama. Jadi jika saya memiliki dua catatan dengan bidang ID,First,Last,Notesdan catatan 1,Bob,Smith,NULLdan 2,Bob,Smith,Arrearskemudian melakukan SELECT *Max(ID), First,Last,Notes FROM DupeTable group by First,Lastkeduanya akan mengembalikan catatan yang sama, 1, kecuali dengan ID yang berbeda. Max (ID) akan kembali 2,Bob,Smith,NULLdan Min (ID) akan kembali 1,Bob,Smith,NULL. Untuk mendapatkan catatan kedua dengan `Tunggakan 'di catatan, saya harus bergabung.
user3649739

7

Berikut ini berfungsi untuk semua tabel

CREATE TABLE `noDup` LIKE `Dup` ;
INSERT `noDup` SELECT DISTINCT * FROM `Dup` ;
DROP TABLE `Dup` ;
ALTER TABLE `noDup` RENAME `Dup` ;

6

Ini jawaban sederhana:

delete a from target_table a left JOIN (select max(id_field) as id, field_being_repeated  
    from target_table GROUP BY field_being_repeated) b 
    on a.field_being_repeated = b.field_being_repeated
      and a.id_field = b.id_field
    where b.id_field is null;

Ini jawaban yang bagus, kecuali kesalahan keciland a.id_field = b.id
Vikrant Goel

The LEFT JOINuntuk bhanya perlu untuk membandingkan b.id= a.id_fieldasumsi field_idadalah ID kenaikan otomatis unik. begitu a.field_being_repeated = b.field_being_repeatedjuga asing. (juga b.id_fieldtidak ada dalam permintaan ini b.id.
ebyrob

6

Ini berfungsi bagi saya untuk menghapus catatan lama:

delete from table where id in 
(select min(e.id)
    from (select * from table) e 
    group by column1, column2
    having count(*) > 1
); 

Anda dapat mengganti min (e.id) ke maks (e.id) untuk menghapus catatan terbaru.


5
delete p from 
product p
inner join (
    select max(id) as id, url from product 
    group by url 
    having count(*) > 1
) unik on unik.url = p.url and unik.id != p.id;

1
Saya menemukan bahwa solusi yang jauh lebih baik daripada yang di atas
Christian Butzke

5

Saya menemukan solusi Werner di atas menjadi yang paling nyaman karena berfungsi terlepas dari keberadaan kunci utama, tidak mengacaukan tabel, menggunakan sql polos yang tahan masa depan, sangat mudah dimengerti.

Seperti yang saya nyatakan dalam komentar saya, solusi itu belum dijelaskan dengan baik. Jadi ini milikku, berdasarkan itu.

1) tambahkan kolom boolean baru

alter table mytable add tokeep boolean;

2) menambahkan batasan pada kolom yang digandakan DAN kolom yang baru

alter table mytable add constraint preventdupe unique (mycol1, mycol2, tokeep);

3) setel kolom boolean menjadi true. Ini akan berhasil hanya pada salah satu baris yang digandakan karena kendala baru

update ignore mytable set tokeep = true;

4) hapus baris yang belum ditandai sebagai tokeep

delete from mytable where tokeep is null;

5) jatuhkan kolom yang ditambahkan

alter table mytable drop tokeep;

Saya menyarankan Anda menjaga batasan yang Anda tambahkan, sehingga duplikat baru dicegah di masa mendatang.


4

Prosedur ini akan menghapus semua duplikat (termasuk kelipatan) dalam sebuah tabel, menjaga duplikat terakhir. Ini adalah perpanjangan dari Mengambil catatan terakhir di setiap grup

Semoga ini bermanfaat bagi seseorang.

DROP TABLE IF EXISTS UniqueIDs;
CREATE Temporary table UniqueIDs (id Int(11));

INSERT INTO UniqueIDs
    (SELECT T1.ID FROM Table T1 LEFT JOIN Table T2 ON
    (T1.Field1 = T2.Field1 AND T1.Field2 = T2.Field2 #Comparison Fields 
    AND T1.ID < T2.ID)
    WHERE T2.ID IS NULL);

DELETE FROM Table WHERE id NOT IN (SELECT ID FROM UniqueIDs);

4

Cara mudah lainnya ... menggunakan UPDATE IGNORE:

Anda harus menggunakan indeks pada satu atau beberapa kolom (ketik indeks). Buat kolom referensi sementara baru (bukan bagian dari indeks). Di kolom ini, Anda menandai unik dengan memperbarui dengan mengabaikan klausa. Selangkah demi selangkah:

Tambahkan kolom referensi sementara untuk menandai uniques:

ALTER TABLE `yourtable` ADD `unique` VARCHAR(3) NOT NULL AFTER `lastcolname`;

=> ini akan menambahkan kolom ke tabel Anda.

Perbarui tabel, coba tandai semuanya sebagai unik, tetapi abaikan kemungkinan kesalahan karena masalah duplikat kunci (catatan akan dilewati):

UPDATE IGNORE `yourtable` SET `unique` = 'Yes' WHERE 1;

=> Anda akan menemukan catatan duplikat Anda tidak akan ditandai sebagai unik = 'Ya', dengan kata lain hanya satu dari setiap set rekaman duplikat akan ditandai sebagai unik.

Hapus semua yang tidak unik:

DELETE * FROM `yourtable` WHERE `unique` <> 'Yes';

=> Ini akan menghapus semua catatan duplikat.

Jatuhkan kolom ...

ALTER TABLE `yourtable` DROP `unique`;

Saya pikir ini adalah solusi terbaik karena tidak mengacaukan tabel dan menggunakan sql sederhana. Satu-satunya hal yang harus diperjelas: uniquekolom HARUS ditambahkan ke batasan unik bersama dengan kolom yang saat ini diduplikasi, jika tidak semuanya bekerja karena SET unique= 'Ya' tidak akan pernah gagal.
xtian

Perlu diketahui juga bahwa itu uniqueadalah kata kunci mysql. Jadi itu harus memiliki backticks (seperti yang sudah ditampilkan dengan benar). Menggunakan kata lain untuk kolom mungkin lebih nyaman.
Torsten

2

Menghapus duplikat pada tabel MySQL adalah masalah umum, yang biasanya disertai dengan kebutuhan spesifik. Jika ada yang tertarik, di sini ( Hapus baris duplikat di MySQL ) Saya menjelaskan cara menggunakan tabel sementara untuk menghapus duplikat MySQL dengan cara yang andal dan cepat, juga berlaku untuk menangani sumber data besar (dengan contoh untuk berbagai kasus penggunaan).

Ali , dalam kasus Anda, Anda dapat menjalankan sesuatu seperti ini:

-- create a new temporary table
CREATE TABLE tmp_table1 LIKE table1;

-- add a unique constraint    
ALTER TABLE tmp_table1 ADD UNIQUE(sid, title);

-- scan over the table to insert entries
INSERT IGNORE INTO tmp_table1 SELECT * FROM table1 ORDER BY sid;

-- rename tables
RENAME TABLE table1 TO backup_table1, tmp_table1 TO table1;

0
delete from `table` where `table`.`SID` in 
    (
    select t.SID from table t join table t1 on t.title = t1.title  where t.SID > t1.SID
)

Ini menghasilkan SQL Error (1093) pada beberapa konfigurasi dan versi MySQL.
ebyrob

0

Love @ eric menjawab tetapi tampaknya tidak berhasil jika Anda memiliki meja yang sangat besar (saya mengerti The SELECT would examine more than MAX_JOIN_SIZE rows; check your WHERE and use SET SQL_BIG_SELECTS=1 or SET MAX_JOIN_SIZE=# if the SELECT is okayketika saya mencoba menjalankannya). Jadi saya membatasi permintaan bergabung hanya mempertimbangkan baris duplikat dan saya berakhir dengan:

DELETE a FROM penguins a
    LEFT JOIN (SELECT COUNT(baz) AS num, MIN(baz) AS keepBaz, foo
        FROM penguins
        GROUP BY deviceId HAVING num > 1) b
        ON a.baz != b.keepBaz
        AND a.foo = b.foo
    WHERE b.foo IS NOT NULL

Klausa WHERE dalam hal ini memungkinkan MySQL untuk mengabaikan setiap baris yang tidak memiliki duplikat dan juga akan mengabaikan jika ini adalah contoh pertama dari duplikat sehingga hanya duplikat berikutnya yang akan diabaikan. Ubah MIN(baz)untuk MAX(baz)mempertahankan instance terakhir, bukan yang pertama.


0

Ini berfungsi untuk tabel besar:

 CREATE Temporary table duplicates AS select max(id) as id, url from links group by url having count(*) > 1;

 DELETE l from links l inner join duplicates ld on ld.id = l.id WHERE ld.id IS NOT NULL;

Untuk menghapus perubahan terlama max(id)menjadimin(id)


0

Ini di sini akan membuat kolom column_namemenjadi kunci utama, dan sementara itu mengabaikan semua kesalahan. Jadi itu akan menghapus baris dengan nilai duplikat untuk column_name.

ALTER IGNORE TABLE `table_name` ADD PRIMARY KEY (`column_name`);

Seperti disebutkan dalam komentar pada jawaban sebelumnya, ini tidak lagi berfungsi dalam 5.7.
Barmar

0

Saya pikir ini akan bekerja dengan pada dasarnya menyalin tabel dan mengosongkannya kemudian hanya mengembalikan nilai yang berbeda ke dalamnya, tetapi harap periksa kembali sebelum melakukannya pada sejumlah besar data.

Membuat salinan karbon dari meja Anda

buat tabel temp_table seperti oldtablename; masukkan temp_table select * from oldtablename;

Kosongkan tabel asli Anda

HAPUS * dari oldtablename;

Menyalin semua nilai yang berbeda dari tabel yang disalin kembali ke tabel asli Anda

INSERT oldtablename SELECT * dari grup temp_table dengan nama depan, nama belakang, dob

Hapus tabel temp Anda.

Jatuhkan Tabel temp_table

Anda perlu mengelompokkan berdasarkan bidang aLL yang Anda ingin tetap berbeda.


0
DELETE T2
FROM   table_name T1
JOIN   same_table_name T2 ON (T1.title = T2.title AND T1.ID <> T2.ID)

itu tidak berfungsi permintaan Anda, bisakah Anda memperbaikinya?
Samir Guiderk

0

di sini adalah bagaimana saya biasanya menghilangkan duplikat

  1. tambahkan kolom sementara, beri nama apa pun yang Anda inginkan (saya akan merujuk sebagai aktif)
  2. dikelompokkan berdasarkan bidang yang menurut Anda tidak boleh duplikat dan aktifkan ke 1, pengelompokan berdasarkan akan memilih hanya satu dari nilai duplikat (tidak akan memilih duplikat) untuk kolom itu
  3. hapus yang nol aktif
  4. drop kolom aktif
  5. opsional (jika sesuai dengan tujuan Anda), tambahkan indeks unik untuk kolom-kolom tersebut agar tidak memiliki duplikat lagi

-2

Anda hanya bisa menggunakan klausul yang berbeda untuk memilih "dibersihkan" daftar (dan di sini adalah contoh yang sangat mudah tentang cara untuk melakukan itu).


Bagaimana itu menjawab pertanyaan? Menggunakan DISTINCTAnda kehilangan semua informasi tentang duplikat yang mungkin Anda miliki di tempat pertama. Bisakah Anda menunjukkan cara untuk menghapus duplikat menggunakannya?
luk2302

-3

Bisakah ini berfungsi jika Anda menghitungnya, dan kemudian menambahkan batas ke permintaan penghapusan Anda hanya menyisakan satu?

Misalnya, jika Anda memiliki dua atau lebih, tulis kueri Anda seperti ini:

DELETE FROM table WHERE SID = 1 LIMIT 1;

-5

Hanya ada beberapa langkah dasar saat menghapus data duplikat dari tabel Anda:

  • Cadangkan meja Anda!
  • Temukan baris duplikat
  • Hapus baris duplikat

Ini tutorial lengkapnya: https://blog.teamsql.io/deleting-duplicate-data-3541485b3473


Apakah itu berfungsi jika id unik hanya berbeda. Bagaimana cara menggunakan id farklı ise de bu işe yarar ma?
Andrew

Secara default metode yang dijelaskan di sini tidak berfungsi untuk versi MySQL> 5.7.5. Ini karena penanganan ONLY_FULL_GROUP_BY. Lihat di sini: dev.mysql.com/doc/refman/5.7/en/group-by-handling.html
delatbabel
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.