2013-04-07 9 views
7

Ho una tabella:Il modo più efficiente per eliminare tutte le righe duplicate dalla tabella?

| foo | bar | 
+-----+-----+ 
| a | abc | 
| b | def | 
| c | ghi | 
| d | jkl | 
| a | mno | 
| e | pqr | 
| c | stu | 
| f | vwx | 

voglio cancellare tutti righe contenenti i duplicati da foo colonna in modo che la tabella dovrebbe essere simile a questo:

| foo | bar | 
+-----+-----+ 
| b | def | 
| d | jkl | 
| e | pqr | 
| f | vwx | 

Qual è il più efficiente modo di fare questo?

risposta

9

È possibile partecipare a una tabella da una sottoquery che restituisce solo foo univoco utilizzando LEFT JOIN. Le righe che non hanno una corrispondenza sul subquery verranno eliminati come desiderato, ad esempio

DELETE a 
FROM TableName a 
     LEFT JOIN 
     (
      SELECT foo 
      FROM TableName 
      GROUP BY Foo 
      HAVING COUNT(*) = 1 
     ) b ON a.Foo = b.Foo 
WHERE b.Foo IS NULL 

per prestazioni più veloci, aggiungere un indice su colonna di Foo.

ALTER TABLE tableName ADD INDEX(foo) 
+0

Questo funziona perfetto, ma è troppo lento (ho una molto grande tabella). –

+0

aggiungi un indice sulla colonna in modo che funzioni più velocemente, ad esempio, 'ALTER TABLE tableName ADD INDEX (foo)' e guarda le prestazioni. –

+0

Grazie ma l'ho già fatto. Ma è il modo più veloce per farlo, comunque, vedo. –

8

Utilizzando EXISTS:

DELETE a 
    FROM TableName a 
WHERE EXISTS (SELECT NULL 
       FROM TableName b 
       WHERE b.foo = a.foo 
      GROUP BY b.foo 
       HAVING COUNT(*) > 1) 

Utilizzando IN:

DELETE a 
    FROM TableName a 
WHERE a.foo IN (SELECT b.foo 
        FROM TableName b 
       GROUP BY b.foo 
       HAVING COUNT(*) > 1) 
+0

Se sono corretto, la versione esistente che hai scritto qui è significativamente più veloce della versione in. Con questo in mente, c'è qualche argomento per la versione in? – usumoio