2009-03-23 9 views
7

J'ai donné à un client la requête suivante pour supprimer le numéro de téléphone en double. enregistrements dans une base de données MSSQL, mais maintenant ils doivent également le faire sur MySQL, et ils signalent que MySQL se plaint du format de la requête. J'ai inclus la configuration d'une table de test avec des doublons pour mon exemple de code, mais la requête de suppression réelle est ce qui compte. Je demande ceci dans l'ignorance et l'urgence, car je suis toujours occupé à télécharger et à installer MySQL, et peut-être que quelqu'un peut aider dans le même temps.Comment faire pour supprimer des doublons dans la table MySQL

create table bkPhone 
(
    phoneNo nvarchar(20), 
    firstName nvarchar(20), 
    lastName nvarchar(20) 
) 
GO 

insert bkPhone values('0783313780','Brady','Kelly') 
insert bkPhone values('0845319792','Mark','Smith') 
insert bkPhone values('0834976958','Bill','Jones') 
insert bkPhone values('0845319792','Mark','Smith') 
insert bkPhone values('0828329792','Mickey','Mouse') 
insert bkPhone values('0834976958','Bill','Jones') 

alter table bkPhone add phoneId int identity 

delete from bkPhone 
where phoneId not in 
(
    select min(phoneId) 
    from bkPhone 
    group by phoneNo,firstName,lastName 
    having count(*) >= 1 
) 
+1

Cela me semble bien. Utilisent-ils une version de MySQL qui supporte les sous-requêtes? –

+0

Pourquoi 'avoir compte (*)> = 1' ?? Quand est-ce jamais? – RichardTheKiwi

Répondre

14

De nombreux chemins mènent à Rome. C'est un. C'est très rapide. Vous pouvez donc l'utiliser avec de grandes bases de données. Ne pas oublier les indeces. L'astuce est: rendre le téléphone unique et utiliser "ignorer".

drop table if exists bkPhone_template; 
create table bkPhone_template (
     phoneNo varchar(20), 
     firstName varchar(20), 
     lastName varchar(20) 
); 

insert into bkPhone_template values('0783313780','Brady','Kelly'); 
insert into bkPhone_template values('0845319792','Mark','Smith'); 
insert into bkPhone_template values('0834976958','Bill','Jones'); 
insert into bkPhone_template values('0845319792','Mark','Smith'); 
insert into bkPhone_template values('0828329792','Mickey','Mouse'); 
insert into bkPhone_template values('0834976958','Bill','Jones'); 

drop table if exists bkPhone; 
create table bkPhone like bkPhone_template; 
alter table bkPhone add unique (phoneNo); 

insert ignore into bkPhone (phoneNo,firstName,lastName) select phoneNo,firstName,lastName from bkPhone_template; 

drop table bkPhone_template; 

Si la table de données existe déjà, il vous suffit d'exécuter une sélection de table create avec un insert suivant ignorer select. À la fin, vous devez exécuter des instructions de changement de nom de table. C'est tout.

Cette solution de contournement est beaucoup, beaucoup plus rapide qu'une opération de suppression.

+0

Merci pour une formation en deux parties sur MySQL. J'ai maintenant 'like' pour créer une table, et 'ignore' dans mon arsenal. – ProfK

+2

Note BTW (commentaire longtemps après la réponse due à la liaison en double) que vous pouvez simplement utiliser ALTER IGNORE TABLE ADD UNIQUE (phoneNo) ', qui jsut silencieusement rejette les doublons dans la table sans avoir à en créer un autre. – Wrikken

5

Vous pouvez sélectionner sur les uniques par:

select distinct(phoneNo) from bkPhone 

et les mettre dans une autre table, supprimer l'ancienne table et renommer le nouveau à l'ancien nom. MySQL se plaint, parce que cela n'a aucun sens.

+0

Compte tenu de la simplicité du scénario, permettant des tables nouvelles et abandonnées, c'était le plus simple. solution la plus efficace. Merci. – ProfK

2

Vous essayez d'agréger en utilisant la colonne min() par laquelle vous regroupez.

Maintenant, si vous essayez de supprimer les numéros de téléphone en double pour la même personne, le SQL doit être:

delete from bkPhone 
where phoneId not in 
(
     select min(phoneId) 
     from bkPhone 
     group by firstName,lastName /* i.e. grouping by person and NOT grouping by phoneId */ 
     having count(*) >= 1 
) 
+0

Génial. Encore un autre cas d'utilisation pour cette belle clause 'having' :-) Mais je pense que vous devriez écrire'> ', au lieu de'> = '. Cela pourrait accélérer les choses –

+0

Je ne vois pas le point de ce 'avoir 'du tout. À l'heure actuelle, cela devrait toujours être vrai, alors c'est inutile. Et si vous le changez en '> 1', alors les lignes * sans * doublons seront omises de l'intérieur' select' et donc * enlevées * par le 'delete' externe. Pas ce que tu voudrais, je crois. – MvG

+0

@LukasEder: avec '>' qui supprimerait toutes les entrées, qui n'ont qu'un seul téléphone. Je pense que vous n'avez pas remarqué qu'il n'y a pas de condition dans la condition. – vartec

Questions connexes