2011-08-18 13 views
5

Tengo un conjunto n: n de datos (por ejemplo, 'programadores' e 'idiomas'. Los programadores escriben código en muchos idiomas, y un lenguaje puede ser usado por muchos programadores). Esta información está en una tabla programmers_languages ​​Instrucción MYSQL para seleccionar rápidamente un grupo de n: n tabla

¿Cómo selecciono rápidamente programadores que codifican en un conjunto de idiomas?

Más información si esto es confuso:

códigos de Jon en C++, Pascal, y Ruby. Joe codifica en C++ y Ruby. Códigos Moe en Ruby y Pascal. Steve Codes en C++ y Pascal.

Si el conjunto de idiomas en cuestión es C++ y Pascal, me gustaría que Jon y Steve de esta lista.

Tenga en cuenta que el tamaño de este conjunto puede ser bastante grande, por lo que no quiero unirme a la tabla n veces.

+0

No estoy seguro si estoy feliz o triste de que esta pregunta, que está en la familia de 'column =" foo "AND column =" bar "' atrape tantas respuestas incorrectas. – SingleNegationElimination

+0

¿Existe solo una tabla, o hay más tablas en este escenario? ¿Y solo tiene dos idiomas, o es una cantidad variable de idiomas en los que podría estar filtrando? – Thorin

+0

Una tabla y número variable de idiomas. Pero sería aceptable si manejara solo 4 idiomas o menos. –

Respuesta

4

Nota el tamaño de este conjunto puede ser bastante grande, por lo que no quieren unirse a la mesa en sí mismo n veces.

Cualquier forma en que lo sacuda, habrá una unión para cada idioma. Está buscando un valor (programador) para el que exista al menos una fila para cada uno de otro valor (idioma). Eso significa que debe pensar en N perspectivas diferentes de la misma tabla.

En la mayoría de los casos, probablemente sea más eficiente para usted hacer las uniones. Si el conjunto de resultados es suficientemente denso (en realidad, la mayoría de los programadores hablan pitón y C++), puede recurrir a cierta astucia. En primer lugar consultar la disyunción, pero de forma única, a continuación, el grupo relación resultante por el programador y filtrar los que hablan idiomas muy pocos ...

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 

Pero esta wether supera un ol regular' de múltiples vías unión se va a depender de los datos exactos en cuestión. Esto al menos tiene la ventaja de no requerir consultas generativas en función del número de idiomas en cuestión.

+0

+1 para señalar que las uniones son probablemente más eficaces la mayor parte del tiempo. Sin embargo, sería interesante escuchar qué tan grande es el conjunto de datos. – Thorin

+0

Los datos son aproximadamente 550,000 filas, donde hay ~ 6000 "programadores" y ~ 1800 "idiomas". El rendimiento es un problema, ya que habrá 50 personas que acierten este db a la vez (esta consulta se usa con moderación, pero no puedo tenerlo bloqueando la base de datos durante 20 segundos). –

+0

Esta es una buena respuesta ... Simplemente deprimente. Me sorprende que no haya una manera eficiente de agrupar datos por programador, y luego mirar a cada programador para verificar un conjunto de n idiomas. Con el tamaño de los datos, una auto unión 4x sería una locura. –

-1

editar: esta fue mi primera respuesta y no funciona para la pregunta.

Asumiendo la tabla Programmers_Languages tiene dos VARCHAR columnas, una llamada Programmer y la otra llamada Languages:

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

DISTINCT de manera que usted consigue solamente una vez cada resultado. ORDER BY si lo quiere ordenado alfabéticamente.


edición: consulta diferente, esto funciona.

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

Parece que TokenMacGuy se le ocurrió algo muy similar. Supongo que la lista de idiomas y el recuento de idiomas se insertarán en esta consulta mediante algún otro código. Si usted está construyendo la consulta de forma dinámica, lo siguiente sería aún más rápido, por supuesto:

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

No. Esto selecciona a los programadores que hablan al menos uno de esos idiomas, pero corykendall pidió una consulta que solo produce los programadores que los hablan a todos. – SingleNegationElimination

+0

Eso no funciona, necesita una lista de personas que coincidan con TODOS los elementos, no solo 1. –

+0

Excelente punto, muchachos, mis ojos cansados ​​malinterpretaron el "y" como un "o". Además, @corykendall, excelente pregunta! – Thorin

Cuestiones relacionadas