2009-03-23 10 views
7

Le he dado a un cliente la siguiente consulta para eliminar el número de teléfono duplicado. registros en una base de datos MSSQL, pero ahora también deben hacerlo en MySQL, e informan que MySQL se queja del formato de la consulta. He incluido la configuración de una tabla de prueba con duplicados para mi muestra de código, pero la consulta de eliminación real es lo que cuenta.Cómo eliminar duplicados en la tabla de MySQL

Lo pregunto por ignorancia y urgencia, ya que todavía estoy ocupado descargando e instalando MySQL, y tal vez alguien pueda ayudar mientras tanto.

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

Me parece bien. ¿Están usando una versión de MySQL que admite subconsultas? –

+0

¿Por qué 'tener count (*)> = 1' ?? Cuando alguna vez NO? – RichardTheKiwi

Respuesta

14

Muchos caminos conducen a Roma. Este es uno. Es muy rápido. Entonces puedes usarlo con grandes bases de datos. No te olvides de los indeces. El truco es: make phoneNo unique y use "ignore".

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 tabla de datos ya existe, solo tiene que ejecutar una tabla de creación seleccionar con una siguiente inserción ignorar seleccionar. Al final, debe ejecutar algunas sentencias de cambio de nombre de la tabla. Eso es todo.

Esta solución es mucho, mucho más rápida que una operación de eliminación.

+0

Gracias por una formación en dos partes en MySQL. Ahora tengo 'me gusta' para crear tabla, e 'ignorar' en mi arsenal. – ProfK

+2

Nota BTW (comentario largo después de la respuesta debido al enlace duplicado) que puede usar 'ALTER IGNORE TABLE ADD UNIQUE (phoneNo)', que silenciosamente descarta los duplicados en la tabla sin tener que crear otro. – Wrikken

5

Puede seleccionar los únicos por:

select distinct(phoneNo) from bkPhone 

y ponerlos en otra tabla, eliminar la tabla de edad y cambiar el nombre nuevo al viejo nombre.

+0

Dada la simplicidad del escenario, permitiendo tablas nuevas y descartadas, esta era la más simple. la solución más efectiva. Gracias. – ProfK

2

MySQL se queja, porque no tiene sentido. Intenta agregar utilizando la columna min() con la que agrupa.

Ahora, si usted está tratando de eliminar números de teléfono duplicados para la misma persona, el SQL debe ser:

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

Impresionante. Otro caso de uso para esa encantadora cláusula 'having' :-) Pero creo que deberías escribir'> ', en lugar de'> = '. Eso podría acelerar las cosas –

+0

No veo el sentido de este 'tener' en absoluto. Tal como está, siempre debe ser cierto, por lo que no tiene sentido. Y si lo cambia a '> 1', entonces las filas * sin * duplicados se omitirán de la 'selección' interna y por lo tanto * se eliminarán * por la 'eliminación' externa. No es lo que querrías, creo. – MvG

+0

@LukasEder: con '>' que eliminaría todas las entradas, que tienen solo un teléfono. Creo que no te diste cuenta de que hay 'no' en la condición. – vartec

Cuestiones relacionadas