Mysql
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Mysql

MySQL xóa các bản ghi trùng lặp nhưng giữ lại bản mới nhất

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 , bbbeee đượ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)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PHP để lưu trữ hình ảnh trong MySQL hay không?

  2. Giới thiệu về các lệnh SQL

  3. Chọn một máy chủ tìm kiếm toàn văn bản độc lập:Sphinx hay SOLR?

  4. Cách lấy số bit trong chuỗi trong MySQL - BIT_LENGTH ()

  5. Làm cách nào để tạo các đối tượng json lồng nhau bằng cách sử dụng các hàm json bản địa của mysql?