2013-05-07 21 views
5

l'obiettivo della query è anche trovare possibili duplicati di nomi che sono stati digitati in modo errato. Esempio:Aggiunta di più condizioni a MySQL Inner Join

International Group Inc. deve essere trovare come un duplicato di International, Group Inc

Al fine di raggiungere questo obiettivo un usato la query successiva:

SELECT C.id, 
     C.name, 
     C.address, 
     C.city_id 
FROM company C 
     INNER JOIN (SELECT name 
        FROM company 
        GROUP BY name 
        HAVING Count(id) > 1) D 
       ON Replace(Replace(C.name, '.', ''), ',', '') = 
        Replace(Replace(D.name, '.', ''), ',', '') 

Funziona molto bene e il risultato è venuto a 40 secs, ma l'aggiunta di un condizioni extra come AND C.city_id='4' richiedono un minuto extra o più; Questo è ancora accettabile ma non preferibile.

Il mio vero problema si verifica quando provo ad aggiungere un'altra condizione per scoprire solo i duplicati di aziende che hanno una stringa specifica nel nome, usando questa condizione AND C.name LIKE '%International%', questo non restituisce alcun risultato.

Qualcuno potrebbe aiutarmi a capire cosa sto facendo male?

Grazie

+0

Purtroppo, io non credo che si possa fare un uso efficiente degli indici in questo scenario - anche se uno minuti + sembra estremamente lento. – Strawberry

risposta

6

Perché si stanno unendo sul risultato di una funzione, la query non è possibile utilizzare qualsiasi indice. Inoltre, il costo di esecuzione di REPLACE() su tutte le righe non è probabilmente trascurabile.

vi suggerisco prima di aggiungere una colonna indicizzata che riceve la versione "stripped-down" delle corde, e quindi eseguire la query con un join su questa colonna:

ALTER TABLE company ADD COLUMN stripped_name VARCHAR(50); 
ALTER TABLE company ADD INDEX(stripped_name); 
UPDATE TABLE company SET stripped_name = REPLACE(REPLACE(name, '.', ''), ',', '') ; 

Esecuzione del UPDATE potrebbe prendere una mentre è la prima volta, ma è anche possibile impostare un trigger ON UPDATE e un ON INSERT su company in modo che venga popolato e aggiornato al volo.

+0

Questa è una grande idea - e ovvia (anche se non ci avevo pensato!) – Strawberry

+0

Questa soluzione incrementa davvero le prestazioni, ma non riesco ancora a ottenere il risultato quando cerco una stringa specifica nel nome dell'azienda che usa 'AND E.stripped_name LIKE '% International%''. Perché potrebbe essere? – gustyaquino

+1

@gustyaquino Sei sicuro che ci sia una riga corrispondente? È possibile che si stia utilizzando una regola di confronto con distinzione tra maiuscole e minuscole. Per favore mostraci la struttura completa della tua tabella ('SHOW CREATE TABLE company;') – RandomSeed

0

Prova a partire dal tavolo tmp perché fila foreach nell'azienda verrà creato un tavolo tmp:

SELECT C.id, 
     C.name, 
     C.address, 
     C.city_id 
FROM (SELECT name 
        FROM company 
        GROUP BY name 
        HAVING Count(id) > 1) D 
INNER JOIN company C  
       ON Replace(Replace(C.name, '.', ''), ',', '') = 
        Replace(Replace(D.name, '.', ''), ',', '')