2011-08-18 8 views
5

Ho un n: n set di dati (ad esempio "programmatori" e "lingue" .I programmatori scrivono il codice in molte lingue e una lingua può essere utilizzata da molti programmatori). Questi dati sono in una tabella programmers_languages ​​Istruzione MYSQL per selezionare rapidamente il gruppo dalla n: n tabella

Come faccio a selezionare rapidamente i programmatori che codificano in un insieme di lingue?

Maggiori informazioni se questo è fonte di confusione:

codici Jon in C++, Pascal, e Ruby. Codici Joe in C++ e Ruby. Codici di Moe in Ruby e Pascal. Steve Codes in C++ e Pascal.

Se il set di lingue in questione è C++ e Pascal, vorrei Jon e Steve da questo elenco.

Nota la dimensione di questo set può diventare piuttosto grande, quindi non voglio unirmi al tavolo n volte.

+0

Non sono sicuro se sono felice o triste che questa domanda, che è nella famiglia di 'column =" foo "AND column =" bar "' cattura così tante risposte sbagliate. – SingleNegationElimination

+0

C'è solo una tabella o ci sono più tabelle in questo scenario? Ed è sempre e solo due lingue, o è un numero variabile di lingue che potresti filtrare? – Thorin

+0

Una tabella e un numero variabile di lingue. Ma sarebbe accettabile se gestisse solo 4 o meno lingue. –

risposta

4

nota la dimensione di questo insieme può ottenere abbastanza grande, quindi non voglio unire la tabella di stesso n volte.

In qualsiasi modo lo si scuota, ci sarà un join per ogni lingua. Stai cercando un valore (programmatore) per il quale esiste almeno una riga per ogni altro valore (lingua). Ciò significa che devi pensare a N diverse prospettive della stessa tabella.

Nella maggior parte dei casi, è probabilmente più efficiente per voi solo fare i join. Se il set di risultati è sufficientemente denso (in realtà, la maggior parte dei programmatori parla python e C++), potresti ricorrere a un po 'di intelligenza. In primo luogo interrogare la disgiunzione, ma unico, poi la relazione di gruppo risultante dal programmatore e filtrare quelli che parlano troppo poche lingue ...

SELECT programmer 
FROM (SELECT DISTINCT programmer, language 
     FROM speaks_table 
     WHERE language in ('C++', 'python')) AS disjunction 
GROUP BY disjunction.programmer 
HAVING count(disjunction.language) = 2 

Ma montone castrato questo supera una ol normale' più vie join sta per dipendere da i dati esatti in questione. Questo ha almeno il vantaggio di non richiedere query generative a seconda del numero di lingue in questione.

+0

+1 per indicare che i join sono probabilmente più efficienti il ​​più delle volte. Sarebbe interessante sapere quanto sia grande il set di dati, comunque. – Thorin

+0

I dati sono circa 550.000 righe, dove ci sono ~ 6000 "programmatori" e ~ 1800 "lingue". Le prestazioni sono un problema, poiché ci saranno persone che colpiscono questo db contemporaneamente (questa query viene usata con parsimonia, ma non posso farla bloccare il database per 20 secondi). –

+0

Questa è una buona risposta ... Semplicemente deprimente. Sono sorpreso che non ci sia un modo efficiente per raggruppare i dati per programmatore, e quindi guardare ogni programmatore a sua volta per verificare un insieme di n lingue. Con la dimensione dei dati, un auto-join 4x sarebbe pazzesco. –

-1

modifica: questa è stata la mia prima risposta e non funziona per la domanda.

Supponendo che il tavolo Programmers_Languages ha due VARCHAR colonne, uno chiamato Programmer e l'altra chiamata Languages:

SELECT DISTINCT Programmer 
FROM Programmers_Languages 
WHERE Language IN ('C++', 'Pascal') 
ORDER BY Programmer 

DISTINCT in modo che si ottiene solo una volta ogni risultato. ORDER BY se lo vuoi ordinare in ordine alfabetico.


modificare: query diversa, questo funziona.

SELECT Programmers 
FROM Programmers_Languages 
WHERE Languages IN ('C++', 'Pascal') 
GROUP BY Programmers 
HAVING COUNT(*) >= 2 
ORDER BY Programmers 

Sembra che TokenMacGuy abbia trovato qualcosa di molto simile. Suppongo che l'elenco delle lingue e il numero di lingue saranno inseriti in questa query da qualche altro codice. Se si sta costruendo la query in modo dinamico, il seguente sarebbe ancora più veloce, ovviamente:

SELECT DISTINCT Programmers 
FROM Programmers_Languages 
WHERE Languages = 'C++' 
AND Languages = 'Pascal' 
AND <...> 
ORDER BY Programmers 
+0

No. Questo seleziona i programmatori che parlano almeno una di quelle lingue, ma corykendall ha chiesto una query che produce solo i programmatori che parlano tutti loro. – SingleNegationElimination

+0

Che non funziona - ha bisogno di un elenco di persone che corrispondono a TUTTI gli articoli, non solo 1. –

+0

Punto eccellente, ragazzi, i miei occhi stanchi hanno letto male "e" come un "o". Inoltre, @corykendall, ottima domanda! – Thorin

Problemi correlati