Méthode pour supprimer les doublons dans une base de données SQL

Les doublons dans une base de données prennent de la place inutilement et peuvent causer des erreurs sur un site web ou une application. Dans un précédent article des requêtes SQL pour trouver les doublons étaient présentées. Cet article-ci présente une requête pour supprimer les doublons tout en conservant une ligne.

ATTENTION : avant de commencer à exécuter la requête de suppression, il faut penser à faire un backup (cf. une sauvegarde) de la table concernée. Dans le pire des cas, il sera possible de la ré-installer.

Supprimer les doublons d'une table

Supprimer les doublons d’une table

Rappel : requête pour trouver les doublons

Avant de vouloir supprimer les éventuels doublons, il faut commencer par vérifier s’il y en a. La requête suivante est à utiliser en remplaçant les champs 1 à 3 par les champs de votre choix qui doivent servir de référentiel pour trouver les lignes dupliquées.

SELECT   COUNT(*) AS nbr_doublon, champ1, champ2, champ3
FROM     table
GROUP BY champ1, champ2, champ3
HAVING   COUNT(*) > 1

Attention, selon le type de lignes dupliquées, il ne faut peut-être pas faire de recherche en utilisant les champs qui servent de timestamp (exemple : un champ DATETIME).

Requête pour supprimer les doublons

Si la requête précédente à bien retournée des résultats considéré comme des doublons, alors il est temps de passer à l’étape suivante pour préparer la suppression. La requête ci-dessous sert à supprimer les lignes en trop qui possèdent les même données dans les colonnes « champ1 » à « champ3 » (à personnaliser).

DELETE FROM table
LEFT OUTER JOIN (
        SELECT MIN(id) as id, champ1, champ2, champ3
        FROM table
        GROUP BY champ1, champ2, champ3
    ) as t1 
    ON table.id = t1.id
WHERE t1.id IS NULL

Attention, il y a plusieurs choses à savoir à propos de cette requête :

  • Le champ « id » est à personnaliser selon le nom de la colonne de votre propre table.
  • La requête va conserver la ligne avec l’ID le plus petit car la fonction MIN() est utilisée. Il est possible de conserver la requête avec l’ID le plus grand en utilisant à la place la fonction MAX().
  • Cette requête assume qu’aucun champ n’est NULL.

Solution n°2

DELETE t1 
FROM table AS t1, table AS t2
WHERE t1.id > t2.id
AND t1.column1 = t2.column1
AND t1.column2 = t2.column2
AND t1.column3 = t2.column3

Vérifier

Il faut songer à vérifier que tout s’est bien passé après avoir supprimé toutes ces lignes. Il est possible de contrôler qu’il n’y a plus de doublons. S’il y en a toujours, c’est le moment de recommencer en corrigeant la requête. Si au contraire trop de lignes ont été supprimées, il faut ré-installer la sauvegarde pour ne pas perdre inutilement des lignes.

A noter : il existe d’autres manières de supprimer les doublons. N’hésitez pas à utiliser une autre technique si vous n’êtes pas à l’aise avec celle-ci.

Ce contenu a été publié dans Astuces.

A propos de l'auteur : Tony Archambeau

Fort de plusieurs années d’expérience dans le développement web, Tony partage ses connaissances sur des projets divers dont le site infowebmaster.fr.
Il est possible de le suivre sur Twitter.

Partager

10 réflexions au sujet de « Méthode pour supprimer les doublons dans une base de données SQL »

  1. Staffent dit :

    Bonjour,

    Et merci pour les requêtes, pour trouver les doublons cela fonctionne très bien, pour les supprimer voici le message :
    debug : #1064 – You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘LEFT OUTER JOIN ( SELECT MIN(ID) as ID, post_title, post_content, post_e’ at line 2{« success »:false, »error »: »
    #1064 – You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘LEFT OUTER JOIN (\n SELECT MIN(ID) as ID, post_title, post_content, post_e’ at line 2″}

    Si vous pouviez m’aider.

    Nicolas

  2. develle dit :

    Bonjour,
    la requête delete ne fonctionnait pas chez moi je l’ai faite ainsi, en ajoutant table avant le from:

    DELETE table FROM table
    LEFT OUTER JOIN (
    SELECT MIN(id) as id, champ1, champ2, champ3
    FROM table
    GROUP BY champ1, champ2, champ3
    ) as t1
    ON table.id = t1.id
    WHERE t1.id IS NULL

  3. yannick dit :

    @develle c’est a fonctionné chez toi ? parce que moi aucune fonctionne :(

  4. Jluc dit :

    Excellent… j’ai aussi ajouter le nom de la table avant le FROM
    DELETE table FROM table
    LEFT OUTER JOIN (
    SELECT MIN(id) as id, champ1, champ2, champ3
    FROM table
    GROUP BY champ1, champ2, champ3
    ) as t1
    ON table.id = t1.id
    WHERE t1.id IS NULL

    fonctionne très bien.

  5. Lerario dit :

    Bonjour,

    Pourriez-vous m’écrire la requête sql pour supprimer les doublons dans ma table mais uniquement les doublons du champ `meta_key`

    Voici ma table :

    CREATE TABLE IF NOT EXISTS `wp_usermeta` (
    `umeta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
    `user_id` bigint(20) unsigned NOT NULL DEFAULT ‘0’,
    `meta_key` varchar(255) DEFAULT NULL,
    `meta_value` longtext,
    PRIMARY KEY (`umeta_id`),
    KEY `user_id` (`user_id`),
    KEY `meta_key` (`meta_key`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=18907 ;

    D’avance merci :-)

  6. Patrick dit :

    DELETE table FROM table
    Et bien c’est incroyable, j’ai pédalé des heures
    2 x la TABLE et ça marche………………………….
    C’est ici que je l’ai trouvé, MERCI

  7. Sigiste dit :

    Salut,

    J’utilise postgresql en association avec postgis

    mon champs id = gid

    j’ai effectué la requête écrite précédemment

    DELETE
    FROM « BOCAGE_table_complete »
    LEFT OUTER JOIN (
    SELECT MIN(« gid ») as « gid », « DATE_TRVX », « LONGUEUR », « NOM_INTERL »
    FROM « BOCAGE_table_complete »
    GROUP BY « DATE_TRVX », « LONGUEUR », « NOM_INTERL »
    ) as t1
    ON table.gid = t1.gid
    WHERE t1.gid IS NULL

    Celle ci ne marche pas.

    J’ai mis la table avant et après le FROM :

    DELETE « BOCAGE_table_complete »
    FROM « BOCAGE_table_complete »
    LEFT OUTER JOIN (
    SELECT MIN(« gid ») as « gid », « DATE_TRVX », « LONGUEUR », « NOM_INTERL »
    FROM « BOCAGE_table_complete »
    GROUP BY « DATE_TRVX », « LONGUEUR », « NOM_INTERL »
    ) as t1
    ON table.gid = t1.gid
    WHERE t1.gid IS NULL

    ça ne marche toujours pas.

    Est ce que cette requête fonctionne avec postgresql ? est ce quelqu’un voit où se trouve le problème ?

  8. mathieu dit :

    Bonjour,

    je ne souhaite pas effacer les doublons, mais les identifier comme tels, donc mettre à jour un champ status. Ma requete ci-dessous ne fonctionne pas, avez-vous une idée de la raison:

    update ma_table
    LEFT OUTER JOIN (
    SELECT MIN(id) as id, username
    FROM ma_table
    GROUP BY username
    ) as t1
    ON table.id = t1.id
    WHERE t1.id IS NULL
    set status = ‘DUPLICATE’

    avec ma_table contenant id (clé), username, status

    une petite aide serait vraiment appréciée :) merci

  9. zatrouch dit :

    faire une copie dans une table temporaire avec un select distinct et le tour est joué sans prise de tête.
    cordialement.

  10. Xavier dit :

    Merci Tony.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *