2012-02-02 12 views
13

En MySQL:seleccionar filas de una tabla en la fila de otra tabla con el mismo id tiene un valor particular en otra columna

si tenemos dos tablas:

comments 
key | value 
================= 
1  | foo 
2  | bar 
3  | foobar 
4  | barfoo 

y:

meta 
comment_key | value 
========================= 
1    | 1 
2    | 1 
3    | 2 
4    | 1 

Quiero obtener los comentarios de la tabla comment que tienen un correspondiente comment_key en la tabla meta que tienen unespecífico 10 (la columna value en la tabla meta).

Por ejemplo, me gustaría seleccionar todas las filas de la tabla comment que tienen un value de 1 en la tabla meta:

yo esperaría que estos resultados:

key | value 
================= 
1  | foo 
2  | bar 
4  | barfoo 

Y si tuviera que seleccionar todas las filas de la tabla comment que tienen un value de 2 en la tabla meta:

me esperaba este resultado:

key | value 
================= 
3  | foobar 

Realmente espero que alguien pueda ayudar, gracias a todos por adelantado!

Creo que necesito hacer una unión? Cualquier sugerencia sería genial, y si es posible, una breve explicación para que pueda determinar dónde estaba yendo mal -> así sabré para la próxima vez.

Respuesta

20

En realidad, no recomendaría un JOIN para este — o más bien, recomendaría un "semijoin", que es un concepto de álgebra relacional no expresado directamente en SQL. Un semijoin es esencialmente una unión en la que desea recuperar registros de una sola tabla, pero con la condición de que tengan registros correspondientes en una tabla diferente.

En la notación de SQL, este concepto se expresa indirectamente, mediante el uso de an IN clause, con un subquery:

SELECT key, value 
    FROM comments 
WHERE key IN 
     (SELECT comment_key 
      FROM meta 
      WHERE value = 1 
     ) 
; 

(MySQL en realidad va a terminar la traducción que de nuevo en un Semiunión internamente — esencialmente una especie de degenerado Intimo únase a — pero la cláusula IN es la forma natural de expresarlo en SQL sin procesar.)

+1

corrección - no importa si se usan predicados 'join',' exists' o 'in', todos son Semi Joins - definidos como combinaciones que devuelven filas de una tabla en función de la existencia de filas relacionadas en otra tabla. –

+2

@JCooper: No lo veo de esa manera. Supongamos que por cada registro en 'parent', hay cero, uno o más registros en' child'. Entonces, una semi unión incluiría cero o una copia de cada registro 'padre', mientras que un SQL 'INNER JOIN' incluiría múltiples copias de algunos registros 'parent'. Pero puedo verlo a tu manera. En el álgebra relacional, una semi unión es equivalente a una unión interna seguida de una proyección apropiada; así que podemos tomar esto como una diferencia entre las proyecciones SQL 'SELECT 'y de álgebra relacional en lugar de entre las combinaciones de SQL' INNER JOIN' y relage-algebra. – ruakh

+1

Guau, estaba tan cerca, ¡solo tenía '=' en lugar de 'IN'! Gracias, funciona un placer! –

0

Está buscando una unión simple, vainilla aquí.

SELECT `comment`.`key` AS `key`, 
     `comment`.`value` AS `value` 
    FROM `comments` 
     JOIN `meta` 
      ON `comments`.`key` = `meta`.`comment_key` 
    WHERE `meta`.`value` = 1; 

No estoy muy seguro de qué tipo de consejo que usted está buscando aquí, pero se puede leer más sobre el tema (no específica MySQL) en Wikipedia's SQL JOIN page.

me gustaría recomendar la indexación en comment. key y meta. comment_key con ambos índices PRIMARY KEY suponiendo que solo quiere que haya 1 meta fila por comment fila (LAS CLAVES PRIMARIAS son ÚNICAS por definición).Si desea permitir más de 1 meta por comment, agregue una columna de índice id por separado a meta y haga que la LLAVE PRIMARIA con comment_key sea simplemente un índice de árbol b.

Tampoco estoy seguro de cómo se comparará el rendimiento de este con la respuesta de "semi-join", pero, para mí, esta es la forma más simple y más natural de expresar la consulta; con solo dos tablas, sin embargo, no debería ser demasiado desafiante para que MySQL optimice.

+0

No estoy seguro de si mencionar índices es sobre pasar la pregunta inapropiadamente o no. Acabo de ver demasiados programadores que no los consideran, ya que las consultas siempre se ejecutan rápidamente en los datos de prueba con una docena de filas por tabla o menos. – SnowCrash

+0

¿Esto no daría como resultado filas duplicadas en el elemento primario si hay varias filas secundarias? – CMCDragonkai

0

yo usaría "INNER JOIN" de la siguiente manera:

SELECT comments.key, comments.value FROM comments 
INNER JOIN meta ON comments.key=meta.comment_key WHERE meta.value = 1; 

Salud! ;-)

Cuestiones relacionadas