2010-10-26 6 views
0

Mon code actuel est le suivant:MySQL many-to-many: Aide Avec la requête

$select = $this->select() 
       ->from(array('r' => 'recipes'), $this->getAdapter() 
                ->quoteInto("r.*, MATCH(title, directions) AGAINST(?) AS score", $searchText)) 
       ->where('MATCH(title, directions) AGAINST(?)', $searchText); 

//SQL: SELECT r.*, MATCH(title, directions) AGAINST('chicken soup') AS `score` FROM `recipes` AS `r` WHERE (MATCH(title, directions) AGAINST('chicken soup')) 

Je veux ajouter une clause WHERE supplémentaire pour trouver que les recettes qui contiennent un certain ingrédient. Le problème que j'ai vient du fait que la table des ingrédients et ma table de recettes ont une relation plusieurs-à-plusieurs, avec une table de connexion ingredients_recipes qui a les colonnes 'id', 'recipe_id' et 'ingredient_id'.

Comment faire?

+0

Pouvez-vous donner plus d'informations sur la configuration que vous utilisez, par ex. le cadre ou la classe d'abstraction de la base de données? –

+0

J'utilise Zend Framework, mais j'ai mis en place le SQL et une réponse juste en langage SQL serait géniale. – moteutsch

Répondre

0

Voici le SQL simple pour rechercher des recettes par ingrédient. Vous devriez pouvoir extrapoler les détails à partir de là.

SELECT r.* 
FROM recipes r 
LEFT OUTER JOIN recipe_ingredients ri ON r.recipe_id = re.recipe_id 
LEFT OUTER JOIN ingredients i on ri.ingredient_id = i.ingredient_id 
WHERE i.ingredient_title = "[Your Ingredient Variable]" 
GROUP BY r.recipe_id; 

Pour plusieurs ingrédients:

SELECT r.* 
FROM recipes r 
LEFT OUTER JOIN recipe_ingredients ri ON r.recipe_id = re.recipe_id 
LEFT OUTER JOIN ingredients i on ri.ingredient_id = i.ingredient_id 
WHERE i.ingredient_title = "[First Ingredient Var]" 
OR i.ingredient_title = "[Second Ingredient Var]" 
GROUP BY r.recipe_id; 

Bien que si vous essayez de trouver quelque chose qui a à la fois (et pas seulement l'un ou l'autre), vous devrez peut-être faire deux requêtes (ou au moins un sous-select), qui peut être une requête assez lente sur une grande base de données.

Le mieux que je peux penser à une seule requête serait quelque chose comme ceci:

SELECT r.* 
FROM recipes r 
LEFT OUTER JOIN recipe_ingredients ri ON r.recipe_id = re.recipe_id 
LEFT OUTER JOIN ingredients i1 on ri.ingredient_id = i1.ingredient_id 
LEFT OUTER JOIN ingredients i2 on ri.ingredient_id = i2.ingredient_id 
WHERE i1.ingredient_title = "[First Ingredient Var]" 
AND i2.ingredient_title = "[Second Ingredient Var]" 
GROUP BY r.recipe_id; 

Si vous créez une jointure pour chaque ingrédient supplémentaire. Cette requête ne renverrait pas les recettes qui contenaient certains - mais pas tous - les ingrédients, seulement des recettes qui ont TOUS les ingrédients que vous recherchez.

+0

Merci c'est génial. Comment, cependant, puis-je trouver une recette qui a deux ingrédients, par exemple une recette qui a à la fois «sel» et «beurre»? – moteutsch

+0

@moteutsch Mise à jour de ma réponse pour plusieurs ingrédients – enobrev

0

Je ne suis pas très familier avec MySQL, mais pourrait-on faire quelque chose de similaire?

SELECT r.* 
FROM recipes AS r 
LEFT JOIN recipe_sites AS s ON r.site_id = s.id 
WHERE '%salt%' IN (SELECT i.name 
        FROM ingredients AS i 
        LEFT JOIN recipe_ingredients AS ri ON i.id = ri.ingredient_id 
        LEFT JOIN recipes AS r ON ri.recipe_id = r.id) 
GROUP BY r.id; 

Quelle serait la bonne façon de procéder?