2009-03-23 9 views
7

Ho assegnato a un cliente la seguente query per eliminare il numero di telefono duplicato. registra in un database MSSQL, ma ora devono farlo anche su MySQL e riportano che MySQL si lamenta del formato della query. Ho incluso l'installazione di una tabella di test con duplicati per il mio esempio di codice, ma la query di eliminazione effettiva è ciò che conta.Come eliminare i duplicati nella tabella MySQL

Lo chiedo in termini di ignoranza e urgenza, dato che sono ancora impegnato a scaricare e installare MySQL, e forse qualcuno può aiutare nel frattempo.

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

Mi sembra soddisfacente. Stanno usando una versione di MySQL che supporta le subquery? –

+0

Perché avere un conteggio (*)> = 1' ?? Quando mai è NOT? – RichardTheKiwi

risposta

14

Molte strade portano a Roma. Questo è uno. È molto veloce Quindi puoi usarlo con grandi database. Non dimenticare gli indeces. Il trucco è: rendere il telefono non esclusivo e utilizzare "ignora".

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; 

Se la tabella di dati esiste già, allora è sufficiente eseguire un tavolo creare selezionare con un seguito inserto ignorare selezionare. Alla fine devi eseguire alcune istruzioni di ridenominazione della tabella. È tutto.

Questa soluzione è molto, molto più veloce di un'operazione di eliminazione.

+0

Grazie per una formazione in due parti su MySQL. Ora ho "mi piace" per creare un tavolo e "ignoro" nel mio arsenale. – ProfK

+2

Nota BTW (commento molto dopo risposta a causa di collegamenti duplicati) che puoi semplicemente usare 'ALTER IGNORE TABELLA AGGIUNGI UNICO (telefonoNo)', che jsut ignora i duplicati nella tabella senza doverne creare un altro. – Wrikken

5

È possibile selezionare le quelle uniche da:

select distinct(phoneNo) from bkPhone 

e metterli in un'altra tabella, eliminare la vecchia tabella e rinominare il nuovo al vecchio nome.

+0

Data la semplicità dello scenario, consentendo tabelle nuove e scartate, questa era la più semplice. soluzione più efficace. Grazie. – ProfK

2

MySQL si lamenta, perché non ha senso. Stai cercando di aggregare usando la colonna min() in base alla quale ti raggruppi.

Ora, se si sta cercando di eliminare i numeri di telefono duplicati per la stessa persona, la SQL dovrebbe essere:

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

Fantastico. Ancora un altro caso d'uso per quella adorabile clausola 'having' :-) Ma penso che dovresti scrivere'> ', invece di'> = '. Questo potrebbe accelerare le cose –

+0

Non vedo affatto il senso di questo "avere". Così com'è, dovrebbe sempre essere vero, quindi è inutile. E se lo si cambia in '> 1', le righe * senza * duplicati sarebbero omesse dall'interno' select' e quindi * rimosse * dall'esterno 'delete'. Non è quello che vorresti, credo. – MvG

+0

@LukasEder: con '>' questo eliminerebbe tutte le voci, che hanno un solo telefono. Penso che tu non abbia notato che non c'è 'non' nella condizione. – vartec