407 votes

Supprimer les lignes dupliquées dans MySQL

J'ai une table avec les champs suivants:

 id (Unique)
url (Unique)
title
company
site_id
 

Maintenant, je dois supprimer les lignes ayant le même titre, la même société et le même nom de site. Une façon de le faire sera d'utiliser le SQL suivant avec un script (PHP):

 SELECT title, site_id, location, id, count( * ) 
FROM jobs
GROUP BY site_id, company, title, location
HAVING count( * ) >1
 

Après avoir exécuté cette requête, je peux supprimer les doublons en utilisant un script côté serveur. Mais, je veux savoir si cela peut être fait seulement en utilisant la requête SQL.

633voto

Chris Henry Points 5191

Vraiment un moyen facile de le faire est d'ajouter un UNIQUE index sur 3 colonnes. Lorsque vous écrivez l' ALTER déclaration, comprennent l' IGNORE mot-clé. Comme suit:

MODIFIER IGNORER TABLE jobs AJOUTER UN INDEX UNIQUE idx_name (site_id, title, company );

Cela supprime toutes les lignes en double. Comme un avantage supplémentaire, à l'avenir, INSERTs sont des doublons erreur. Comme toujours, vous pouvez faire une sauvegarde avant de lancer quelque chose comme ça...

199voto

rehriff Points 11

Si vous ne souhaitez pas modifier les propriétés de la colonne, vous pouvez utiliser la requête ci-dessous.

Puisque vous avez une colonne qui a un identifiant unique ou une colonne qui a des propriétés auto_increment, vous pouvez utiliser cette colonne pour supprimer les doublons.

 DELETE a
FROM jobs as a, jobs as b
WHERE
          (a.title   = b.title OR a.title IS NULL AND b.title IS NULL)
      AND (a.company = b.company OR a.company IS NULL AND b.company IS NULL)
      AND (a.site_id = b.site_id OR a.site_id IS NULL AND b.site_id IS NULL)
      AND b.ID > a.ID;
 

Idéalement, il existe de nombreuses façons, la meilleure façon est ce qui associe vos propriétés de table / colonne.

80voto

Andomar Points 115404

MySQL a des restrictions sur la référence à la table que vous supprimez. Vous pouvez contourner cela avec une table temporaire, comme:

 create temporary table tmpTable (id int);

insert  tmpTable
        (id)
select  id
from    YourTable yt
where   exists
        (
        select  *
        from    YourTabe yt2
        where   yt2.title = yt.title
                and yt2.company = yt.company
                and yt2.site_id = yt.site_id
                and yt2.id > yt.id
        );

delete  
from    YourTable
where   ID in (select id from tmpTable);
 

48voto

Kamil Maraz Points 633

Si l'instruction IGNORE ne fonctionne pas comme dans mon cas, vous pouvez utiliser:

 CREATE TABLE your_table_deduped like your_table;
INSERT your_table_deduped SELECT * FROM your_table GROUP BY index1_id, index2_id;
RENAME TABLE your_table TO your_table_with_dupes;
RENAME TABLE your_table_deduped TO your_table;
#OPTIONAL
ALTER TABLE `your_table` ADD UNIQUE `unique_index` (`index1_id`, `index2_id`);
#OPTIONAL
DROP TABLE your_table_with_dupes;
 

7voto

Eduardo Rascon Points 402

J'ai cette snipet de requête pour SQLServer mais je pense qu'il peut être utilisé dans d'autres SGBD avec peu de changements:

 DELETE
FROM Table
WHERE Table.idTable IN  (  
    SELECT MAX(idTable)
    FROM idTable
    GROUP BY field1, field2, field3
    HAVING COUNT(*) > 1)
 

J'ai oublié de vous dire que cette requête ne supprime pas la ligne avec l'ID le plus bas des lignes dupliquées. Si cela fonctionne pour vous essayez cette requête:

 DELETE
FROM jobs
WHERE jobs.id IN  (  
    SELECT MAX(id)
    FROM jobs
    GROUP BY site_id, company, title, location
    HAVING COUNT(*) > 1)
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X