Sören: [MySQL] 1:n Beziehung alles in einem query abfragen.

Hallo,

Ich hab mal wieder eine Frage zu Datenbankabfragen.

Dieses mal handelt es sich um eine 1:n Beziehung das wie folgt aussieht:

1. Tabelle messages:
id message
1    ...
2    ...
3    ...

2. Tabelle message_zusatz:
messageid zusatz
    1      ...
    1      ...
    2      ...
    2      ...
    2      ...
    3      ...

Wie kann ich nun in einem query alle Daten abfragen?

Ich habe mir das ungefähr so vorgestellt:

  
SELECT messages.message, zusatz1.zusatz, zusatz2.zusatz  
   FROM messages  
   LEFT JOIN message_zusatz AS zusatz1 ON zusatz1.messageid = messages.id  
   LEFT JOIN message_zusatz AS zusatz2 ON zusatz2.messageid = messageid

Dies würde klappen, wenn ich wüsste wieviele Datensätze sich aus message_zusatz auf messages beziehen (im oben genannten query sind es 2) die Anzahl kann jedoch variieren von message zu message.

Gruß Sören

  1. Hi,

    Ich hab mal wieder eine Frage zu Datenbankabfragen.

    Bitte gewöhne dir ab, dabei den Hinweis, den du beim Anlegen eines neuen Threads in diesem Bereich bekommst, zu ignorieren - dass du bitte Name und Version deines DBMS nennen sollst.

    Wie kann ich nun in einem query alle Daten abfragen?

    Und bitte an, Beispieldaten und damit erwartetes Ergebnis anzugeben.

    MfG ChrisB

    --
    “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
    1. Hi,

      ... bitte Name und Version deines DBMS nennen sollst.

      Den Namen habe ich angegeben. Der steht in der Überschrift. Die Version empfand ich nicht als wichtig, aber zur Vollständigkeit: 5.0.51b

      Und bitte an, Beispieldaten und damit erwartetes Ergebnis anzugeben.

      Die Abfrage soll das gleiche Ergebnis liefern, wie ich es schon in meiner Beispiel Abfrage getan habe, mit der Ausnahme, dass ich gerne alle Ergebnisse aus der 2. Tabelle zu der entsprechenden message hätte und nicht nur die 2 zusatz1.zusatz und zusatz2.zusatz

      Ich hätte also auch gerne zusatz3.zusatz, zusatz4.zusatz, zusatz5.zusatz... falls diese Zusätze existieren.

      Die id der ersten 1. Tabelle steht in der Verbindung mit der messageid aus der 2. Tabelle

      Gruß Sören

      1. Hallo,

        die Version ist immens wichtig, da bei mySQL in früheren Version solche fundamentalen Dinge wie Subqueries oder Stores Procedures nicht unterstützt wurden. In anderen DBMS gibt es ab gewissen Versionen einen PIVOT Operator, der annähernd das macht, was du möchtest, allerdings auch nicht wirklich 100%ig dynamisch.

        Um deine Anforderung umzusetzen, fallen mir auf Anhieb 3 Wege ein:

        • schreibe dynamisches SQL - baue dir also dynamisch mit PHP oder sonst einer passenden Programmiersprache eine entsprechende SQL Abfrage zusammen, welche die Daten pivotiert
        • mach das pivotieren mit PHP (oder sonst ...), das geht recht effektiv mittels Hashtables und Arrays
        • mach es über XSLT, also hol dir die ursprungsdaten in der vertikalen form als XML, schreib ein entsprechendes Stylesheet

        Jede Variante hat vor und Nachteile. Probieren geht über Studieren.

        Ansonsten: Mit all deinen Anfragen bisher stellt sich bei mir das Gefühl ein: Dein gesamtes Datenmodell ist falsch (falsch konzipiert im Hinblick auf die Anforderungen bzw. einfach falsch implementiert) und fordert dir deshalb solch sonderbare Aufgaben ab. Durchdenke es bitte nochmals von grundauf.

        Gruss, Frank

        1. Hallo,

          Ansonsten: Mit all deinen Anfragen bisher stellt sich bei mir das Gefühl ein: Dein gesamtes Datenmodell ist falsch (falsch konzipiert im Hinblick auf die Anforderungen bzw. einfach falsch implementiert) und fordert dir deshalb solch sonderbare Aufgaben ab. Durchdenke es bitte nochmals von grundauf.

          Ja, danke, ich hab das Modell zu dieser Aufgabe nochmal überdacht und bin zu einer anderen besseren Lösung gekommen.

          Bei der vorherigen Anfrage kann ich dir nicht zu stimmen.

          Gruß Sören

  2. Hi!

    Wie kann ich nun in einem query alle Daten abfragen?
    [...]
    Dies würde klappen, wenn ich wüsste wieviele Datensätze sich aus message_zusatz auf messages beziehen (im oben genannten query sind es 2) die Anzahl kann jedoch variieren von message zu message.

    Da du das aber nicht weißt, ist dieser Weg nicht möglich. Du willst quasi aus "senkrechten Daten" mit noch dazu unterschiedlicher Anzahl "waagerechte Daten" machen. Die Anzahl der "waagerechten Daten" ist feststehend und durch die SELECT-Klausel vorgegeben. Man kann sie nicht erweitern, nur verkürzen im gewissen Sinne, wenn man NULL-Werte für nicht belegte Spalten zurückliefert.

    Mir fallen vier Wege ein:

    • Ein einfacher (LEFT) JOIN, dann hast du aber das Problem der Wiederholung der messages-Datensätze je Zusatz.
    • Eine rekursive Abfrage - die man im Prinzip vermeiden will, weil sie eine Menge Einzelanfragen bedeutet.
    • Erst Messages abfragen und eine zweite mit WHERE messageid IN (IDs der Messages aus dem ersten Ergebnis). Nur zwei Abfragen, aber die Zuordnung muss im abfragenden Programm erfolgen.
    • GROUP BY und GROUP_CONCAT(). Damit bekommst du alle Zusätze pro Message als einen String mit Trennzeichen.

    Lo!