2013-04-09 12 views
13

ho tabella come questa2 diversi piccoli interrogazione vs 1 query con sottoquery

name  | personal_number 
----------------------------------------- 
Jon  | 222 
Alex  | 555 
Jon  | 222 
Jimmy  | 999 

ho bisogno di ottenere ogni nome, che personal_number repeates a tavola più di 1, che è risultato deve essere:

Jon   
Jon   

Così, Variante 1):

SELECT name FROM mytable WHERE personal_number IN (
     SELECT personal_number FROM mytable GROUP BY personal_number 
     HAVING COUNT(*) > 1 
) 

Variante 2):

SELECT personal_number FROM mytable GROUP BY personal_number 
     HAVING COUNT(*) > 1 
) 

Quindi, utilizzando php, personal_numbers recuperati join as string (soemthing come questo '222', '222') ed eseguire altra query

SELECT name FROM mytable WHERE personal_number IN(here joined string) 

Variante 2 opere circa 10 volte più veloce, di variante 1, questo è una sorpresa per me, stavo pensando che una query sarà più veloce, ma ...

(Nella tabella è 500 000 righe, colonne personal_number non indicizzata)

Allora, che cosa vuoi dire su casi come questo? perché la variante 2 è molto più veloce della variante 1?

+2

+1 per la buona domanda e per non chiedere prima di eseguire alcuni test di benchmark. – enenen

+2

una SPIEGAZIONE delle due query dovrebbe mostrarlo –

+0

Se nome e numero_dipendente dipendono l'uno dall'altro, si dovrebbe andare e portare la tabella al secondo modulo normale – Argeman

risposta

0

Questo dovrebbe essere più veloce:

SELECT name FROM mytable join (
     SELECT personal_number FROM mytable GROUP BY personal_number 
     HAVING COUNT(*) > 1 
)a using (personel_number) 

Edit: Se questo è più veloce di variante 1, allora significa in variante 1 mysql riproduce la tabella interna per ciascun record ripetutamente.

+2

Questo non spiega la differenza di prestazioni. – Bart

+0

@Bart no, non funziona. – palindrom

0

Poiché l'indicizzazione non viene eseguita, 1 è lento, in quanto deve corrispondere a numero personale di numeri personali selezionati. Se l'indicizzazione viene eseguita, consuma meno tempo rispetto a prima. La variante 2 è una query diretta, quindi è più veloce.

1

La prima query ha subquery pesante. Devi evitare questo. La soluzione migliore per il vostro problema è solo una query:

SELECT name FROM mytable GROUP BY personal_number HAVING COUNT(*) > 1; 

Questa query restituirà voi ogni nome ripetuto una sola volta. Se si desidera visualizzare il nome del duplicato il numero di volte come si sono incontrati è necessario utilizzare query successiva:

SELECT name, COUNT(*) AS count FROM mytable GROUP BY personal_number HAVING COUNT(*) > 1; 

E poi in PHP fare qualcosa del genere:

foreach ($rows as $row) { 
    for ($i = 0; $i++; $i < $row['count']) { 
    echo $row['name'] . "\n"; 
    } 
} 
Problemi correlati