2012-03-31 9 views
1

Ich habe drei Tabellen. Denken Sie an sie als die folgenden:Wie kann ich alle Zeilen in einer Tabelle finden, die ausschließlich verknüpfte Zeilen in einer bestimmten Liste enthalten?

Recipes 
    id | name 
    1 | Cookies 
    2 | Soup 
    ... 


    Ingredients 
    id | name 
    1 | flour 
    2 | butter 
    3 | chicken 
    ... 

    Recipe_Ingredient 
    recipe_id | ingredient_id 
    1   | 1 
    1   | 2 
    2   | 3 

Hoffentlich bekommen Sie die Idee. Was ich möchte ist eine Abfrage, wo ich alle Rezepte finden kann, die Zutaten haben, die eine Teilmenge einer bestimmten Reihe von Zutaten sind.

Die Idee ist, dass ich eine Liste aller Dinge haben möchte ich mit dem, was ich habe auf der Hand machen kann (aber natürlich nicht alles was ich habe auf der Hand.)

Ich habe versucht, die Umsetzung dieses mit verschiedene Ebenen von Unterabfragen und korrelierte Unterabfragen mit EXISTS hatten aber kein Glück. Ich habe auch versucht, HAVING und COUNT zu verwenden, aber das scheint nur für mich zu funktionieren, wenn ich etwas möchte, das ALLE Zutaten verwendet, die ich zur Hand habe.

+0

Sie wollen also Rezepte, die alle ihre Zutaten in der Liste der "verfügbaren" Zutaten sind. Probiere das [sql-match-all] -Tag oder die Links rechts unter ** Related ** header. –

+0

Dies wird [SQL der Relationalen Abteilung] genannt (http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/) –

+0

@ypercube wow, fantastisch. Ja, genau das habe ich versucht, aber ich muss meine Logik irgendwie durcheinander gebracht haben. Danke für die tolle Verbindung –

Antwort

1

Testen Sie dies, wenn es funktioniert. Vorausgesetzt, dass Sie Ihre (unique) Bestandteil ids in einer Tabelle namens ingredients_avail zur Verfügung haben, sollten diese Abfrage das Rezept ID zeigen, dass eine vollständige Zutaten hat:

SELECT recipe_id 
    FROM [select recipe_id, count(*) as num_of_ingredients from recipe_ingredient group by recipe_id]. AS x, [select recipe_ingredient.recipe_id as recipe_id, count(*) as num_of_ingredients 
    from recipe_ingredient, ingredients_avail    
    where    
    recipe_ingredient.ingredient_id = ingredients_avail.ingredient_id 
    group by recipe_ingredient.recipe_id]. AS y    
    WHERE x.recipe_id = y.recipe_id and    
    x.num_of_ingredients = y.num_of_ingredients;    

Zusätzlich ist es hier in einer typischeren Syntax:

SELECT x.recipe_id 
    FROM ( 
     SELECT recipe_id, count(*) as num_of_ingredients 
     FROM recipe_ingredients 
     GROUP BY recipe_id 
    ) x, ( 
     SELECT recipe_id, count(*) as num_of_ingredients 
     FROM recipe_ingredients 
     JOIN ingredients_avail 
      ON recipe_ingredients.ingredient_id = ingredients_avail.ingredient_id 
     GROUP BY recipe_id 
    ) y 
    WHERE x.recipe_id = y.recipe_id AND x.num_of_ingredients = y.num_of_ingredients; 
1
mysql> 
    mysql> select * from ingredients; 
    +------+---------------+-----------+ 
    | id | name   | available | 
    +------+---------------+-----------+ 
    | 1 | salt   | n   | 
    | 2 | sugar   | n   | 
    | 3 | flour   | n   | 
    | 4 | butter  | n   | 
    | 5 | vanilla  | n   | 
    | 6 | baking powder | n   | 
    | 7 | egg   | n   | 
    +------+---------------+-----------+ 
    7 rows in set (0.00 sec) 

    mysql> select * from recipes; 
    +------+---------------+ 
    | id | name   | 
    +------+---------------+ 
    | 1 | cookie  | 
    | 2 | soup   | 
    | 3 | xtreme flavor | 
    +------+---------------+ 
    3 rows in set (0.00 sec) 

    mysql> select * from recipe_ingredient; 
    +-----------+---------------+ 
    | recipe_id | ingredient_id | 
    +-----------+---------------+ 
    |   1 |    1 | 
    |   1 |    2 | 
    |   1 |    3 | 
    |   1 |    4 | 
    |   1 |    5 | 
    |   1 |    6 | 
    |   1 |    7 | 
    |   2 |    1 | 
    |   2 |    7 | 
    |   3 |    4 | 
    |   3 |    3 | 
    +-----------+---------------+ 
    11 rows in set (0.00 sec) 

    mysql> 
    mysql> update ingredients set available = 'n'; 
    Query OK, 0 rows affected (0.00 sec) 
    Rows matched: 7 Changed: 0 Warnings: 0 

    mysql> 
    mysql> update ingredients set available = 'y' 
     -> where id in (1,2,3,4,5,6,7); 
    Query OK, 7 rows affected (0.00 sec) 
    Rows matched: 7 Changed: 7 Warnings: 0 

    mysql> 
    mysql> select recipes.name from 
     -> (select recipe_id, available from 
     -> recipe_ingredient, 
     -> ingredients 
     -> where ingredient_id = ingredients.id 
     -> group by recipe_id, available) x, recipes 
     -> where recipes.id = x.recipe_id 
     -> group by x.recipe_id 
     -> having count(*) = 1 
     -> and max(x.available) = 'y'; 
    +---------------+ 
    | name   | 
    +---------------+ 
    | cookie  | 
    | soup   | 
    | xtreme flavor | 
    +---------------+ 
    3 rows in set (0.06 sec) 

    mysql> 
    mysql> update ingredients set available = 'n'; 
    Query OK, 7 rows affected (0.00 sec) 
    Rows matched: 7 Changed: 7 Warnings: 0 

    mysql> 
    mysql> update ingredients set available = 'y' 
     -> where id in (1,7); 
    Query OK, 2 rows affected (0.00 sec) 
    Rows matched: 2 Changed: 2 Warnings: 0 

    mysql> 
    mysql> select recipes.name from 
     -> (select recipe_id, available from 
     -> recipe_ingredient, 
     -> ingredients 
     -> where ingredient_id = ingredients.id 
     -> group by recipe_id, available) x, recipes 
     -> where recipes.id = x.recipe_id 
     -> group by x.recipe_id 
     -> having count(*) = 1 
     -> and max(x.available) = 'y'; 
    +------+ 
    | name | 
    +------+ 
    | soup | 
    +------+ 
    1 row in set (0.06 sec) 

    mysql> 
    mysql> 
    mysql> update ingredients set available = 'n'; 
    Query OK, 2 rows affected (0.00 sec) 
    Rows matched: 7 Changed: 2 Warnings: 0 

    mysql> 
    mysql> update ingredients set available = 'y' 
     -> where id in (4,3); 
    Query OK, 2 rows affected (0.00 sec) 
    Rows matched: 2 Changed: 2 Warnings: 0 

    mysql> 
    mysql> select recipes.name from 
     -> (select recipe_id, available from 
     -> recipe_ingredient, 
     -> ingredients 
     -> where ingredient_id = ingredients.id 
     -> group by recipe_id, available) x, recipes 
     -> where recipes.id = x.recipe_id 
     -> group by x.recipe_id 
     -> having count(*) = 1 
     -> and max(x.available) = 'y'; 
    +---------------+ 
    | name   | 
    +---------------+ 
    | xtreme flavor | 
    +---------------+ 
    1 row in set (0.05 sec) 

    mysql> 
    mysql> 
    mysql> update ingredients set available = 'n'; 
    Query OK, 3 rows affected (0.00 sec) 
    Rows matched: 7 Changed: 3 Warnings: 0 

    mysql> 
    mysql> update ingredients set available = 'y' 
     -> where id in (1,3,7); 
    Query OK, 3 rows affected (0.00 sec) 
    Rows matched: 3 Changed: 3 Warnings: 0 

    mysql> 
    mysql> select recipes.name from 
     -> (select recipe_id, available from 
     -> recipe_ingredient, 
     -> ingredients 
     -> where ingredient_id = ingredients.id 
     -> group by recipe_id, available) x, recipes 
     -> where recipes.id = x.recipe_id 
     -> group by x.recipe_id 
     -> having count(*) = 1 
     -> and max(x.available) = 'y'; 
    +------+ 
    | name | 
    +------+ 
    | soup | 
    +------+ 
    1 row in set (0.06 sec) 
+0

Funktioniert das richtig, wenn ich Zutaten 1, 3 und 7 zur Verfügung habe? Das heißt, es sollte Suppe zurückgeben, da ich mit 1 und 7 Suppe machen kann. –

+0

@Frew, ja es gibt 'Suppe' zurück, wenn 1, 3 und 7 verfügbar sind. Ich fügte die obigen Ergebnisse hinzu. – oriolussteerii

+0

Ehrfürchtig, danke; Ich werde sehen, ob das für mich funktioniert und wenn ja, erhalten Sie den Kredit :-) –

Verwandte Themen