2011-09-13 26 views
9

Sto provando a selezionare elementi da una tabella associativa che hanno soddisfatto due o più valori dello stesso campo, suoni confusi, lasciatemi spiegare.MySQL Seleziona ID che si verificano su righe diverse con più valori specifici per una colonna

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

Nella tabella, voglio essere in grado di selezionare solo gli elementi che sono nelle categorie che passano. Quindi, per esempio, se passo gli ID di categoria di 201 e 202, vorrei solo gli elementi che sono in ENTRAMBI le categorie (possono avere altre categorie ma devono essere almeno nelle categorie che sto interrogando), quindi in questo caso, vorrei articoli 1 e 2 solo in quanto sono gli unici che sono nelle categorie 201 e 202.

la mia dichiarazione di SQL iniziale era qualcosa di simile

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

Ma, ovviamente, che non funzionerà.

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

Anche la query precedente non funzionerà perché restituirà gli elementi 4 e 3.

Quindi, come sceglierei solo gli elementi che devono essere almeno in entrambe le categorie?

Ricordare che potrei passare più di 2 ID di categoria.

Grazie per il vostro aiuto.

risposta

8

tua espressione in una clausola WHERE lavora contro un singola riga del set di risultati uniti. Ecco perché WHERE category_id = 201 AND category_id = 202 non funziona, perché non può essere due valori su una singola riga.

Quindi è necessario un modo per unire due righe dal tavolo in una riga del set di risultati. Si può fare questo con un self-join:

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 

Questa tecnica è difficile da scalare quando si desidera effettuare la ricerca per tre, quattro, cinque o più valori, perché richiede N-1 unisce per abbinare i valori N.

Quindi un altro metodo è quello di utilizzare 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 

Entrambe le tecniche sono a posto, e lavorare meglio in circostanze diverse.

+0

Grazie, la seconda query sembra essere più adatta in questo caso e sembra funzionare bene! Grazie ancora! – flicker

-2

Si potrebbe provare:

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

(o, come dicono i commenti ... non si può.)

+0

Ciò restituirà item_ids 3 e 4 – Bruce

0

utilizzare un JOIN o 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

Assumendo ogni item_id, category_id è univoco,

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

sostituire C = 2 con c = (conteggio delle categorie)

0

non ho il tempo per fornire la query esatta in questo momento, ma provare qualcosa di simile:

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; 

Forse condizioni sono sbagliato, ma si può provare qualcosa in questo modo.

+0

Non sono sicuro che ic1.item_id = ic2.item_id sia davvero necessario. – martincho

Problemi correlati