Hãy tưởng tượng bảng của bạn test
chứa dữ liệu sau:
select id, email
from test;
ID EMAIL
---------------------- --------------------
1 aaa
2 bbb
3 ccc
4 bbb
5 ddd
6 eee
7 aaa
8 aaa
9 eee
Vì vậy, chúng tôi cần tìm tất cả các email lặp lại và xóa tất cả chúng, trừ id mới nhất.
Trong trường hợp này, aaa
, bbb
và eee
được lặp lại, vì vậy chúng tôi muốn xóa các ID 1, 7, 2 và 6.
Để thực hiện điều này, trước tiên, chúng tôi cần tìm tất cả các email lặp lại:
select email
from test
group by email
having count(*) > 1;
EMAIL
--------------------
aaa
bbb
eee
Sau đó, từ tập dữ liệu này, chúng tôi cần tìm id mới nhất cho từng email lặp lại sau:
select max(id) as lastId, email
from test
where email in (
select email
from test
group by email
having count(*) > 1
)
group by email;
LASTID EMAIL
---------------------- --------------------
8 aaa
4 bbb
9 eee
Cuối cùng, bây giờ chúng ta có thể xóa tất cả các email này với Id nhỏ hơn LASTID. Vì vậy, giải pháp là:
delete test
from test
inner join (
select max(id) as lastId, email
from test
where email in (
select email
from test
group by email
having count(*) > 1
)
group by email
) duplic on duplic.email = test.email
where test.id < duplic.lastId;
Tôi chưa cài đặt mySql trên máy này ngay bây giờ, nhưng sẽ hoạt động
Cập nhật
Cách xóa ở trên hoạt động, nhưng tôi đã tìm thấy một phiên bản được tối ưu hóa hơn:
delete test
from test
inner join (
select max(id) as lastId, email
from test
group by email
having count(*) > 1) duplic on duplic.email = test.email
where test.id < duplic.lastId;
Bạn có thể thấy rằng nó xóa các bản sao cũ nhất, tức là 1, 7, 2, 6:
select * from test;
+----+-------+
| id | email |
+----+-------+
| 3 | ccc |
| 4 | bbb |
| 5 | ddd |
| 8 | aaa |
| 9 | eee |
+----+-------+
Một phiên bản khác, là lệnh xóa được tạo bởi Rene Limon
delete from test
where id not in (
select max(id)
from test
group by email)