2011-09-13 14 views
9

Estoy tratando de seleccionar elementos de una tabla asociativa que han satisfecho dos o más valores del mismo campo, suena confuso, permítame explicarlo.MySQL Seleccione las identificaciones que se producen en diferentes filas con múltiples valores específicos para una columna

+-----------------------+ 
| item_id | category_id | 
+-----------------------+ 
| 1  | 200  | 
| 1  | 201  | 
| 1  | 202  | 
| 2  | 201  | 
| 2  | 202  | 
| 3  | 202  | 
| 3  | 203  | 
| 4  | 201  | 
| 4  | 207  | 
+-----------------------+ 

En la tabla, quiero poder seleccionar solo los elementos que están en las categorías que paso. Entonces, por ejemplo, si paso las ID de categoría 201 y 202, solo quiero elementos que estén en AMBAS categorías (pueden tener otras categorías pero deben estar en al menos las categorías que estoy consultando), entonces en este caso, me gustaría que los puntos 1 y 2 solamente, ya que son los únicos que se encuentran en las categorías 201 y 202.

Mi declaración inicial de SQL era algo así como

SELECT * FROM item_category WHERE category_id = 201 AND category_id = 202; 

Pero obviamente eso no funcionará.

SELECT * FROM item_category WHERE category_id = 201 OR category_id = 202; 

La consulta anterior tampoco funcionará porque devolverá los elementos 4 y 3 también.

Entonces, ¿cómo podría hacer para seleccionar únicamente elementos que al menos deben estar en ambas categorías?

Tenga en cuenta que podría estar pasando más de 2 identificaciones de categoría.

Gracias por su ayuda.

Respuesta

8

Su expresión en una cláusula WHERE funciona en contra de fila única del conjunto de resultados unidos. Es por eso que WHERE category_id = 201 AND category_id = 202 no funciona, porque no puede haber dos valores en una sola fila.

Así que necesita alguna manera de unir dos filas de la tabla en una fila del conjunto de resultados. Puede hacer esto con un autocombinación:

SELECT c1.item_id 
FROM item_category AS c1 
INNER JOIN item_category AS c2 ON c1.item_id = c2.item_id 
WHERE c1.category_id = 201 AND c2.category_id = 202 

Esta técnica es difícil de escalar cuando se quiere buscar tres, cuatro, cinco o más valores, ya que requiere N-1 une para que coincida con N valores.

Así Otro método consiste en utilizar GROUP BY:

SELECT c.item_id, COUNT(*) AS cat_count 
FROM item_category AS c 
WHERE c.category_id IN (201,202) 
GROUP BY c.item_id 
HAVING cat_count = 2 

Ambas técnicas están bien, y trabajar mejor en diferentes circunstancias.

+0

Gracias, la segunda consulta parece ser más adecuado en este caso y parece que funciona bien! ¡Gracias de nuevo! – flicker

-2

Usted podría intentar:

SELECT * FROM item_category WHERE category_id IN (201, 202, ...)

(o, como dicen los comentarios ... puede que no.)

+0

que devolverá item_ids 3 y 4 – Bruce

0

uso ya sea una combinación, o una GROUP BY:

SELECT category_id, fieldhere, anotherfield 
FROM item_category 
WHERE category_id in (201,202) 
GROUP BY category_id 
HAVING count(category_id) = 2 
0

Suponiendo que cada item_id, category_id es único,

select *, count(item_id) as c from item_category 
where category_id in (201, 202) 
group by item_id 
having c = 2; 

Reemplace c = 2 con c = (recuento de categorías)

0

que no tienen el tiempo para proporcionar la consulta exacta en este momento, pero trata de algo como esto:

select item_category.* from 
item_category , item_category ic1, item_category ic2 where 
ic1.category_id = 201 and 
ic2.category_id = 202 and 
ic1.item_id = ic2.item_id and 
item_category.item_id = ic1.item_id and 
item_category.item_id = ic2.item_id; 

Tal vez las condiciones son erróneas, pero se puede probar algo de esta manera.

+0

No estoy seguro de si ic1.item_id = ic2.item_id es realmente necesario. – martincho

Cuestiones relacionadas