2010-07-30 4 views
1

J'ai quatre tables:recherche dans les tableaux communs

cuisines(id, name); 

recipes(id, cuisine_id, name, picture); 

ingredients(id, name); 

ingredients_recipes(ingredient_id, recipe_id); 

la dernière table références many-to-many entre les recettes et les ingrédients. Comment puis-je sélectionner toutes les cuisines qui contiennent des tomates (c'est-à-dire que la cuisine a des recettes qui ont des ingrédients appelés "tomates")?

Je l'utilise dans SQLite mais je suppose que c'est la même chose dans tous les langages SQL?

Répondre

0

Rejoignez tous selon les clés étrangères, filtre = de ingredient_name « Tomatoe », groupe par toutes les colonnes de la table des cuisines qui vous intéresse

SELECT cuisine.id, cuisine.name 
    FROM cuisine 
    INNER JOIN recipe on recipe.cuisine_id = cuisine.id 
    INNER JOIN ingredients_recipes ir ON ir.recipe_id = recipe.id 
    INNER JOIN ingredients on ingredients.id = ir.ingredient_id 
    WHERE ingredients.name = 'Tomatoe' 
    GROUP BY cuisine.id, cuisine.name 
3

Vous pouvez essayer INNER JOIN ing quatre tables, comme dans l'exemple suivant:

SELECT  DISTINCT c.name 
FROM  cuisines AS c 
INNER JOIN recipes AS r ON (r.cuisine_id = c.id) 
INNER JOIN ingredients_recipes AS ir ON (ir.recipe_id = r.id) 
INNER JOIN ingredients AS i ON (i.id = ir.ingredient_id) 
WHERE  i.name = 'tomatoes'; 
+0

Ne serait-ce vous donner répéter les noms de cuisine pour les cuisines qui ont plusieurs recettes avec des tomates? Est-ce que 'SELECT DISTINCT c.name' est nécessaire? – markusk

+0

@markusk: Yep bon point. Soit 'DISTINCT' ou' GROUP BY'. Mise à jour ma réponse –

0

variante de sous-requête.

SELECT name 
FROM cuisines 
WHERE id IN (
    SELECT cuisine_id 
    FROM recipes r 
    JOIN ingredients_recipes ir ON r.id = ir.recipe_id 
    JOIN ingredients i ON ir.ingredient_id = i.id 
    WHERE i.name = 'Tomatoes' 
) 
0

Je suggère d'utiliser des sous-requêtes au lieu des jointures. Quelque chose comme ...

SELECT * 
    FROM cuisine 
    WHERE cuisine_id IN (
      SELECT cuisine_id 
       FROM recipe 
       WHERE recipe_id IN (
         SELECT recipe_id 
          FROM recipe_ingredients 
          WHERE ingredient_id IN (
             SELECT id 
             FROM ingredients 
             WHERE TOUPPER(name) LIKE '%TOMATO%'))); 

Dans tous les cas, je pense que vous devez faire attention à la correspondance sur le mot; Plus que d'autres correspondants ont été, comme vous ne voulez pas manquer des ingrédients comme «Quatre petites tomates» ou «Une grande tomate» ou «purée de tomates».

+0

salut, merci pour cela. Quel est l'avantage des sous-requêtes sur les jointures? – ChrisB

+0

Je trouve les sous-requêtes plus faciles à comprendre que les jointures, et moins sujettes aux erreurs, même si je pense que je suis en minorité à cet égard. Certes, un nid prolongé comme celui ci-dessus n'est pas un exemple particulièrement attrayant. Tu fais ce que tu préfères. On dit souvent que les sous-requêtes sont plus lentes que les jointures; Je n'ai jamais trouvé ça comme ça. L'optimiseur de requête est tout à fait capable de réécrire une sous-requête en tant que jointure s'il le juge approprié. –

+0

Les sous-requêtes sont lentes, tout comme vous l'avez admis. Donc, il n'y a aucune raison d'apprendre à utiliser cela, si vous avez des options plus rapides. – newbie

0

EXISTE variante:

SELECT name 
FROM cuisines c 
WHERE EXISTS 
( SELECT NULL 
    FROM recipes r 
    JOIN ingredients_recipes ir ON r.id = ir.recipe_id 
    JOIN ingredients i ON ir.ingredient_id = i.id and i.name = 'tomatoes' 
    WHERE r.cuisine_id = c.id 
) 
Questions connexes