2010-12-01 31 views
3

J'ai deux tableaux qui sont exposés à peu près comme suit:MySQL aux prises avec la requête en relation un à plusieurs correspondant à plusieurs conditions

products   product_attributes 
================== ======================================== 
| id | name  | | id | product_id | attribute | value | 
================== ======================================== 
| 1 | product 1 | | 1 | 1   | size  | big | 
| 2 | product 2 | | 2 | 1   | colour | red | 
| 3 | product 3 | | 3 | 2   | size  | medium | 
| 3 | product 3 | | 4 | 2   | age_range | 3-5 | 
| .. | ...  | | 5 | 2   | colour | blue | 
================== | 6 | 3   | size  | small | 
        | .. | ...  | ...  | ... | 
        ======================================== 

Il y a potentiellement une quantité infinie d'attributs d'un produit qui est la raison pour laquelle ils sont conservé dans une table séparée. Je veux être capable de sortir des produits distincts qui correspondent à des conditions d'attributs MULTIPLES (également infinies) mais je ne peux pas penser comment le faire sans peut-être utiliser une condition OU puis une sorte de compte pour vérifier tous les attributs apparié. Je suis assez sûr que ce n'est pas le meilleur moyen alors j'espère que quelqu'un peut aider ?! Par exemple, trouvez des produits qui ont la taille = 'moyen' et la couleur = 'bleu' (ceci correspondrait au produit 2 dans l'exemple ci-dessus).

Répondre

7

Ceci est un problème relational division.

La façon dont vous suggérez le COUNT est probablement le plus facile dans MySQL

SELECT product_id 
FROM product_attributes pa 
WHERE (attribute='size' and value='medium') 
OR (attribute='colour' and value='blue') 
GROUP BY product_id 
HAVING COUNT(DISTINCT CONCAT(attribute,value)) = 2 

Il y a une autre approche avec double NOT EXISTS dans l'article lié, mais comme MySQL ne supporte pas CTEs qui serait assez lourd.

+0

merci, c'était en quelque sorte sur les lignes que je pensais, mais j'espérais il y aurait eu un moyen plus efficace. Je sais que c'est très improbable mais ai-je raison de penser que DISTINCT CONCAT (attribut, valeur) pourrait rencontrer des problèmes si j'avais des attributs "siz" et "size" avec des valeurs "esmall" et "small" respectivement? Je sais que c'est improbable, mais je suis confronté à beaucoup de données tierces. Y a-t-il un moyen de garantir une combinaison unique en utilisant l'attribut ID ou quelque chose comme DICTINCT (pa.id)? – atkaye

+0

@atkaye - Oui cela vous causerait un problème. J'ai d'abord utilisé 'COUNT (*)' mais l'ai édité. Avez-vous une contrainte unique sur la combinaison de colonnes 'product_id',' attribute'? c'est-à-dire qu'un produit particulier peut-il avoir une seule valeur pour un attribut particulier? –

+0

Oui, il ne peut y avoir qu'une seule valeur pour un attribut. Y a-t-il une raison pour laquelle vous avez supprimé COUNT (*)? – atkaye

0

Je pense que cela devrait faire l'affaire:

SELECT a.product_id, p.name FROM product_attributes AS a LEFT JOIN products p ON (a.product_id=p.id) WHERE (a.attribute="size" AND a.value="medium") OR (a.attribute="colour" AND a.value="blue") GROUP BY a.product_id 
+0

merci, même que la réponse ci-dessus, je pense, mais il manque juste le nombre de s'assurer que toutes les conditions sont assorties – atkaye