2010-08-29 12 views
7

Tengo una tabla MySQL. Vamos a llamarlo Widgets. La tabla de widgets tiene 3 campos: id, type_id y name. Quiero, en una consulta, obtener todos los widgets que comparten un type_id con el Widget llamado 'doodad'. He escrito 2 consultas:MySQL WHERE-IN Subquery ejecuta Forever

  1. Dame la type_id del widget con el nombre 'doodad'.
  2. Dame todos los widgets con ese type_id.

Esto funciona. Cada consulta, independientemente, logra su objetivo.

Pero cuando los combino en una sola consulta anidada, se ejecuta para siempre, estilo de ciclo infinito. Se ve así:

SELECT * FROM widgets WHERE type_id IN (
    SELECT type_id FROM widgets WHERE name = 'doodad' 
); 

¿Alguien puede explicar esto? ¿Es porque estoy escribiendo una consulta anidada que está operando en la misma tabla dos veces?

Little wheel, why spinnest thou?

Respuesta

6

There is an issue in MySQL y in donde incluso las subconsultas no correlacionadas se tratan como si estuvieran correlacionadas y reevaluadas para cada fila.

En el plan de explicación, el tipo de selección probablemente se mostrará como dependant subquery en lugar de solo subquery como se desee.

Sugiero probar el método descrito at the end of this article de usar una tabla derivada para materializar el conjunto de resultados interno.

O, alternativamente, puede consultar constifyprocedure here para ver si le puede ayudar a solucionar este problema.

+0

La razón por la que estoy usando una subconsulta DONDE-IN se debe a que anteriormente estaba usando un JOIN y contra la base de datos de 2 millones de widgets, tardó más de dos minutos en ejecutarse. Como 2 consultas separadas, el tiempo de ejecución es menor a un segundo. – Whit

+0

@Whit - He encontrado un par de soluciones alternativas que puede intentar ver si puede hacer funcionar el "en". –

+0

No puedo creer que 6 años después de que se inventó constify, esto todavía no es parte de mysql. ¿No es solo un alias para crear manualmente una tabla temporal y unirnos a ella? – fastmultiplication

3

Usando un JOIN riesgos duplicar los resultados - una EXISTE funciona similar a un IN, sin el riesgo de duplicación:

SELECT x.* 
    FROM widgets x 
WHERE EXISTS (SELECT NULL 
       FROM WIDGETS y 
       WHERE y.name = 'doodah' 
        AND y.type_id = x.type_id) 
+0

+1 Buen punto. Sería interesante saber si también funciona mejor para el PO. –

Cuestiones relacionadas