Ulf: SQL-Brett vorm Kopf ...

Hi Forum,

hab grad dickes Brett vorm Kopf und komm nicht auf eine bestimmt total banale SQL-Query:
Hab eine Tabelle der Form "rezepte_zutaten"
mit rezept_id und zutat_id.
In einer Abfrage kann man nun seine vorhandenen Zutaten ankreuzen und es sollen alle Rezepte ausgespuckt werden die darauf passen.
Ich hab momentan folgndes (mit PHP):
$query = "SELECT rezept_id FROM rezepte_zutaten WHERE zutat_id IN (".join($zutaten_ids, ',').")";
Damit bekomm ich aber alle Rezepte die mindestens eine der Zutaten haben und nicht die deren Zutatenliste komplett in der Menge der übergebenen Zutaten-Ids enthalten ist... ?!

Grüße, Ulf

  1. Hiho

    Ich hab momentan folgndes (mit PHP):
    $query = "SELECT rezept_id FROM rezepte_zutaten WHERE zutat_id IN (".join($zutaten_ids, ',').")";

    es soll DB-Experten geben, die kein PHP können. Nur so am Rande...

    Damit bekomm ich aber alle Rezepte die mindestens eine der Zutaten haben und nicht die deren Zutatenliste komplett in der Menge der übergebenen Zutaten-Ids enthalten ist... ?!

    scheint mir auch sinnvoll so, aber wenn du es andersrum willst:
    mit

    SELECT rezept_id FROM rezepte_zutaten WHERE zutat_id NOT IN (zutat1, zutat2 ...)

    erhältst du eine Liste der rezept_id, wo eine Zutat fehlt.
    Der Rest sollte auch mit Brett vorm Kopf leicht sein.

    Gruß
    Wurf

  2. Hi Forum,

    hab grad dickes Brett vorm Kopf und komm nicht auf eine bestimmt total banale SQL-Query:
    Hab eine Tabelle der Form "rezepte_zutaten"
    mit rezept_id und zutat_id.
    In einer Abfrage kann man nun seine vorhandenen Zutaten ankreuzen und es sollen alle Rezepte ausgespuckt werden die darauf passen.
    Ich hab momentan folgndes (mit PHP):
    $query = "SELECT rezept_id FROM rezepte_zutaten WHERE zutat_id IN (".join($zutaten_ids, ',').")";
    Damit bekomm ich aber alle Rezepte die mindestens eine der Zutaten haben und nicht die deren Zutatenliste komplett in der Menge der übergebenen Zutaten-Ids enthalten ist... ?!

    Grüße, Ulf

    Lieber Ulf,

    da mir heute morgen so nett geholfen wurde, will ich mich mal versuchen ;-)))

    Ich denke der Fehler liegt darin dass Du nach ODER und nicht nach UND suchst???

    Suche ich ein Rezept zu Mehl, Eier kriege ich Pudding, Pfannkuchen etc.

    Suche ich aber nur nach Mehl UND Eiern UND nach 2 Zutaten, dann müsste es klappen!

    Am besten ein weiteres Datenbankfeld hinzufügen mit der Anzahl Zutaten...

    Dann im Vorfeld die Anzahl der zu suchenden Zutaten (SELECT COUNT(zutat_id) AS Anzahl_ID...) ermitteln und danach die Abfrage

    SELECT rezept_id FROM rezepte..... WHERE.... AND...

    Ist vielleicht Quatsch aber müsste funzen ;-))))

    Liebe Grüße, Claudi...

  3. Moin!

    hab grad dickes Brett vorm Kopf und komm nicht auf eine bestimmt total banale SQL-Query:

    Nein, die Aufgabenstellung ist alles andere als banal.

    Hab eine Tabelle der Form "rezepte_zutaten"
    mit rezept_id und zutat_id.

    Mit anderen Worten:
    Rezepte:
    Rührei = 1
    Pfannkuchen = 2
    Frühstücksei = 3

    Zutaten:
    Eier = 1
    Mehl = 2
    Milch = 3

    Und verknüpft:
    rezept_id   zutat_id
    1           1
    2           1
    2           2
    1           3
    2           3
    3           1

    Mit anderen Worten: Rührei besteht aus Eiern und Milch, und Pfannkuchen aus Eiern, Mehl und Milch. Das Frühstücksei besteht nur aus Eiern.

    Die Frage ist jetzt, was du die Datenbank fragen willst:

    Mit der Frage "Was enthält neben anderem Zeugs auch Eier oder Milch" bist du bei deinem jetzigen Query. Da kommen dann allerdings alle drei Rezepte bei heraus.

    Alternative Fragemöglichkeiten sind:
    "Was enthält mindestens genau die Zutaten, aber ggf. auch noch mehr?"
    Die Antwort bei "Eiern, Milch" wäre dann Rührei (enthält Eier und Milch) sowie Pfannkuchen (enthält Eier, Milch, und zusätzlich noch Mehl).

    "Was enthält exakt die angegebenen Zutaten?"
    Einzige Antwort bei "Eiern, Milch" wäre dann das Rührei.

    Ich hab momentan folgndes (mit PHP):
    $query = "SELECT rezept_id FROM rezepte_zutaten WHERE zutat_id IN (".join($zutaten_ids, ',').")";

    Damit bekomm ich aber alle Rezepte die mindestens eine der Zutaten haben und nicht die deren Zutatenliste komplett in der Menge der übergebenen Zutaten-Ids enthalten ist... ?!

    Insbesondere bekommst du mit dieser Abfrage jedes Rezept, welches mehr als eine der gewünschten Zutaten hat, mehrfach in deiner SQL-Ergebnisliste aufgeführt.

    Aber genau diesen Effekt kannst du dir zunutze machen:

    SELECT rezept_id, count(rezept_id) as zutatentreffer FROM rezepte_zutaten WHERE zutat_ID IN (1,2) GROUP BY rezept_id HAVING zutatentreffer = 2;

    Du hast zwei Zutaten, fragst also nach allen Rezepten, die zwei Zutaten "richtig" haben.

    Damit kriegst du dann alle Rezepte, die MINDESTENS die geforderten Zutaten enthalten.

    Die Frage nach Rezepten, die EXAKT die geforderten Zutaten enthalten, müßte man prüfen, ob die gefundenen Mindest-Rezepte keine weiteren Zutateneinträge besitzen. Ggf. mit einem Subselect (bei MySQL versionsabhängig erst ab 4.1 verfügbar, IIRC).

    - Sven Rautenberg

    --
    My sssignature, my preciousssss!
  4. hab grad dickes Brett vorm Kopf und komm nicht auf eine bestimmt total banale SQL-Query:

    so ist es

    Damit bekomm ich aber alle Rezepte die mindestens eine der Zutaten haben und nicht die deren Zutatenliste komplett in der Menge der übergebenen Zutaten-Ids enthalten ist... ?!

    du benötigst eine UND bedingung, welche sich über mehrere zeilen erstreckt. diese frage wird zwar alle nase lang gestellt, aber ist wohl immer je nach aufgabenformulierung verwirrend.

    eine UND bedingung über mehrere zeilen wird üblicherweise mit einem self-join erledigt.

    SELECT spalten
    FROM tabelle t1 INNER JOIN tabelle t2 USING(spalte)
    WHERE spalte IN(wert1, wert2 ...)

    für deine anforderung mußt du USING(rezept_id) einsetzen und in der WHERE klausel die zutaten.

    1. nachschlag: sorry, so ist es, wenn man über aufgaben solcher art nicht mehr nachdenkt.

      UND war gefragt. hier muß jedes UND einen SELF-join haben

      antwort:

      SELECT rezept
      FROM tabelle t1 INNER JOIN tabelle t2 USING(rezept) INNER JOIN tabelle t3 USING(rezept) ...
      WHERE t1.zutat1 = wert1 AND t2.zutat2 = wert2 AND t3.zutat3 = wert3 ...

      du mußt je nach anzahl zutaten einen entsprechend langen join zusammen basteln

      eine alternative bestünde tatsächlich darin, mit COUNT über die rezepte zu gruppieren und die anzahl mit der anzahl der zutaten aus der bedingung zu verbinden. (WHERE COUNT = zutatenanzahl)