Mysql
 sql >> Baza danych >  >> RDS >> Mysql

MySQL usuwa zduplikowane rekordy, ale zachowuje najnowsze

Wyobraź sobie swój stół test zawiera następujące dane:

  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 

Musimy więc znaleźć wszystkie powtarzające się e-maile i usunąć je wszystkie, ale najnowszy identyfikator.
W tym przypadku aaa , bbb i eee są powtarzane, więc chcemy usunąć identyfikatory 1, 7, 2 i 6.

Aby to osiągnąć, najpierw musimy znaleźć wszystkie powtarzające się e-maile:

      select email 
        from test
       group by email
      having count(*) > 1;

EMAIL                
-------------------- 
aaa                  
bbb                  
eee  

Następnie z tego zbioru danych musimy znaleźć najnowszy identyfikator dla każdego z tych powtarzających się e-maili:

  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                                 

Wreszcie możemy teraz usunąć wszystkie te e-maile z identyfikatorem mniejszym niż LASTID. Rozwiązaniem jest więc:

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;

Nie mam w tej chwili zainstalowanego mySql na tym komputerze, ale powinien działać

Aktualizacja

Powyższe usuwanie działa, ale znalazłem bardziej zoptymalizowaną wersję:

 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;

Widać, że usuwa najstarsze duplikaty, tj. 1, 7, 2, 6:

select * from test;
+----+-------+
| id | email |
+----+-------+
|  3 | ccc   |
|  4 | bbb   |
|  5 | ddd   |
|  8 | aaa   |
|  9 | eee   |
+----+-------+

Inną wersją jest usuwanie dostarczone przez 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. Zagadnienia dotyczące integralności danych i wydajności w półsynchronicznej replikacji MySQL

  2. Wyszukaj wszystkie wystąpienia ciągu w bazie danych mysql

  3. PHP mysql wstaw format daty

  4. JSON_CONTAINS_PATH() Przykłady w MySQL

  5. Jak znaleźć n-tą pozycję w MySQL?