web-dev-qa-db-fra.com

Comment supprimer tous les enregistrements en double dans une table MySQL sans tables temporaires

J'ai vu un certain nombre de variations à ce sujet, mais rien ne correspond vraiment à ce que j'essaie d'accomplir.

J'ai un tableau, TableA, qui contient les réponses données par les utilisateurs à des questionnaires configurables. Les colonnes sont member_id, quiz_num, question_num, answer_num.

D'une manière ou d'une autre, quelques membres ont reçu leurs réponses deux fois. J'ai donc besoin de supprimer les enregistrements dupliqués, mais assurez-vous qu'il reste une ligne.

Il n'y a pas de colonne primaire donc il pourrait y avoir deux ou trois lignes, toutes avec les mêmes données.

Existe-t-il une requête pour supprimer tous les doublons?

45
MivaScott

Ajoutez nique Index sur votre table:

ALTER IGNORE TABLE `TableA`   
ADD UNIQUE INDEX (`member_id`, `quiz_num`, `question_num`, `answer_num`);

Une autre façon de faire serait:

Ajouter une clé primaire dans votre table, vous pouvez facilement supprimer les doublons de votre table en utilisant la requête suivante:

DELETE FROM member  
WHERE id IN (SELECT * 
             FROM (SELECT id FROM member 
                   GROUP BY member_id, quiz_num, question_num, answer_num HAVING (COUNT(*) > 1)
                  ) AS A
            );
101
Saharsh Shah

Cela n'utilise pas de tables TEMP, mais de vraies tables. Si le problème concerne uniquement les tables temporaires et non la création ou la suppression de tables, cela fonctionnera:

SELECT DISTINCT * INTO TableA_Verify FROM TableA;

DROP TABLE TableA;

RENAME TABLE TableA_Verify TO TableA;
13
christoph

Au lieu de drop table TableA, vous pouvez supprimer tous les registres (delete from TableA;), puis remplissez la table originale avec les registres provenant de TableA_Verify (insert into TAbleA select * from TAbleA_Verify). De cette façon, vous ne perdrez pas toutes les références à la table d'origine (index, ...)

CREATE TABLE TableA_Verify AS SELECT DISTINCT * FROM TableA;

DELETE FROM TableA;

INSERT INTO TableA SELECT * FROM TAbleA_Verify;

DROP TABLE TableA_Verify;
13
jveirasv

Merci à jveirasv pour la réponse ci-dessus.

Si vous devez supprimer les doublons d'un ensemble spécifique de colonnes, vous pouvez l'utiliser (si vous avez un horodatage dans la table qui varie, par exemple).

CREATE TABLE TableA_Verify AS SELECT * FROM TableA WHERE 1 GROUP BY [COLUMN TO remove duplicates BY];

DELETE FROM TableA;

INSERT INTO TableA SELECT * FROM TAbleA_Verify;

DROP TABLE TableA_Verify;
7
nikolais

Ajoutez un index unique sur votre table:

ALTER IGNORE TABLE TableA   
ADD UNIQUE INDEX (member_id, quiz_num, question_num, answer_num);

est le travail très bien

6
Dina Elwy

Si vous n'utilisez aucune clé primaire, exécutez les requêtes suivantes d'un seul coup. En remplaçant les valeurs:

# table_name - Your Table Name
# column_name_of_duplicates - Name of column where duplicate entries are found

create table table_name_temp like table_name;
insert into table_name_temp select distinct(column_name_of_duplicates),value,type from table_name group by column_name_of_duplicates;
delete from table_name;
insert into table_name select * from table_name_temp;
drop table table_name_temp
  1. créer une table temporaire et stocker des valeurs distinctes (non dupliquées)
  2. faire table vide
  3. insérer des valeurs dans la table d'origine à partir de la table temporaire
  4. supprimer la table temporaire

Il est toujours conseillé de faire une sauvegarde de la base de données avant de jouer avec.

3
Sandesh Mhatre

Une autre solution serait de créer une nouvelle table temporaire avec la même structure.

CREATE TABLE temp_table AS SELECT * FROM original_table LIMIT 0

Créez ensuite la clé primaire dans la table.

ALTER TABLE temp_table ADD PRIMARY KEY (primary-key-field)

Enfin, copiez tous les enregistrements de la table d'origine en ignorant les enregistrements en double.

INSERT IGNORE INTO temp_table AS SELECT * FROM original_table

Maintenant, vous pouvez supprimer la table d'origine et renommer la nouvelle table.

DROP TABLE original_table
RENAME TABLE temp_table TO original_table
1
user1838915

Comme indiqué dans les commentaires, la requête dans la réponse de Saharsh Shah doit être exécutée plusieurs fois si les éléments sont dupliqués plus d'une fois.

Voici une solution qui ne supprime aucune donnée et conserve les données dans le tableau d'origine pendant tout le temps, ce qui permet de supprimer les doublons tout en maintenant le tableau 'en direct':

alter table tableA add column duplicate tinyint(1) not null default '0';

update tableA set
duplicate=if(@member_id=member_id
             and @quiz_num=quiz_num
             and @question_num=question_num
             and @answer_num=answer_num,1,0),
member_id=(@member_id:=member_id),
quiz_num=(@quiz_num:=quiz_num),
question_num=(@question_num:=question_num),
answer_num=(@answer_num:=answer_num)
order by member_id, quiz_num, question_num, answer_num;

delete from tableA where duplicate=1;

alter table tableA drop column duplicate;

En gros, cela vérifie si la ligne en cours est identique à la dernière et si elle l’est, la marque comme étant en double (l’instruction order garantit que les doublons apparaîtront côte à côte). Ensuite, vous supprimez les enregistrements en double. Je supprime la colonne duplicate à la fin pour la ramener à son état d'origine.

Ça ressemble à alter table ignore pourrait aussi bientôt disparaître: http://dev.mysql.com/worklog/task/?id=7395

1
juacala