web-dev-qa-db-fra.com

Supprimer toutes les lignes en double, sauf pour One dans MySQL?

Duplicate possible:
Supprimer les lignes en double dans MySQL

Comment supprimer toutes les données en double d'une table MySQL?

Par exemple, avec les données suivantes:

SELECT * FROM names;

+----+--------+
| id | name   |
+----+--------+
| 1  | google |
| 2  | yahoo  |
| 3  | msn    |
| 4  | google |
| 5  | google |
| 6  | yahoo  |
+----+--------+

J'utiliserais SELECT DISTINCT name FROM names; s'il s'agissait d'une requête SELECT.

Comment ferais-je avec DELETE pour ne supprimer que les doublons et ne garder qu'un enregistrement de chacun?

395
Highway of Life

Avertissement de l'éditeur: Cette solution est inefficace du point de vue calcul et peut entraîner la perte de votre connexion pour une table volumineuse.

NB - Vous devez faire ceci en premier sur une copie test de votre table!

Lorsque je l'ai fait, j'ai constaté qu'à moins d'inclure également AND n1.id <> n2.id, toutes les lignes de la table étaient supprimées.

  1. Si vous souhaitez conserver la ligne avec la valeur idla plus basse:

    DELETE n1 FROM names n1, names n2 WHERE n1.id > n2.id AND n1.name = n2.name
    
  2. Si vous voulez conserver la ligne avec la plus haute valeur idname__:

    DELETE n1 FROM names n1, names n2 WHERE n1.id < n2.id AND n1.name = n2.name
    

J'ai utilisé cette méthode dans MySQL 5.1

Pas sûr des autres versions.


Mise à jour: les personnes recherchant Google pour supprimer les doublons se retrouvent ici
Bien que la question du PO porte sur DELETEname__, sachez que l'utilisation de INSERTet de DISTINCTest beaucoup plus rapide. Pour une base de données de 8 millions de lignes, la requête ci-dessous a pris 13 minutes. Si vous avez utilisé DELETEname__, elle a pris plus de 2 heures et n'a pas encore abouti.

INSERT INTO tempTableName(cellId,attributeId,entityRowId,value)
    SELECT DISTINCT cellId,attributeId,entityRowId,value
    FROM tableName;
892
martin.masa

Si vous souhaitez conserver la ligne avec la valeur id la plus basse:

DELETE FROM NAMES
 WHERE id NOT IN (SELECT * 
                    FROM (SELECT MIN(n.id)
                            FROM NAMES n
                        GROUP BY n.name) x)

Si vous voulez que la valeur id soit la plus élevée:

DELETE FROM NAMES
 WHERE id NOT IN (SELECT * 
                    FROM (SELECT MAX(n.id)
                            FROM NAMES n
                        GROUP BY n.name) x)

La sous-requête d'une sous-requête est nécessaire pour MySQL, sinon vous obtiendrez une erreur 1093.

181
OMG Ponies