Fabian: verschachtelte Tabelle abfragen Inner Join Mysql

Hallo Forum Gemeinde,

leider konnte mir im Archiv und handbuch nicht geholfen werden, so dass ich mein Problem einmal hier posten werde. Für eine Antwort wäre ich sehr dankbar.

Meine Datenbank besteht aus drei Tabellen.

Tabelle_A      Tabelle_B       Tabelle_C
-stellen_id    -stellen_id     -ordner_id
-text1         -ordner_id      -unternehmen_id
-text2
-text3

Ich würde gern alle Spalten der Tabelle A ausgeben, wenn in Tabelle_C: $ordner_id = ordner_id AND $unternehmen_id = unternehmen_id

Meine Versuche mit WHERE Abfragen:
$sql = "SELECT text1, text2 FROM Tabelle_A
WHERE (
Tabelle_C.unternehmen_id ='$unternehmen_id'
AND Tabelle_C.ordner_id ='$ordner_id'
AND Tabelle_B.ordner_id = Tabelle_C.ordner_id
AND Tabelle_A.stellen_id = Tabelle_B.stellen_id)";

...sind leider gescheitert.

Das Problem habe ich nun mit einer doppelten WHILE Schleife lösen können:
$result = mysql_query("SELECT stellen_id FROM TABELLE X INNER JOIN TABELLE X ON (Tabelle X.ordner_id = Tabelle X.ordner_id) WHERE (Tabelle X.uid ='$UID' AND Tabelle X.ordner_id='$s_ordner_id')");

while ($row = mysql_fetch_array($result))
{ $stellen_id=$row["stellen_id"];
$sql=  mysql_query("SELECT TABELLE X.text1, text2, text3 FROM Tabelle X WHERE stellen_id='$stellen_id'");
  while ($row = mysql_fetch_array($sql))
  {
   $text1=$row["text1"];
   $text2=$row["text2"];
   $text3=$row["text3"];
  }

echo $text1...
}
Diese Lösung funktioniert zwar, erscheint mir aber wenig praktikabel und uneffektiv.

Wie muß diese jedoch aussehen? Für drei Tabellen (bzw. auch gern für n-Tabellen)?

Auf mein Posting hatte ich bereits eine Antwort bekommen, leider funktioniert diese Lösung jedoch nicht bei mir. Ist die Abfrage denn so generell richtig?

SELECT Tabelle_A.*
FROM Tabelle_C INNER JOIN (Tabelle_A INNER JOIN Tabelle_B ON Tabelle_A.stellen_id = Tabelle_B.stellen_id) ON Tabelle_C.ordner_id = Tabelle_B.ordner_id
WHERE (((Tabelle_B.unternehmen_id)='$unternehmen_id') AND ((Tabelle_C.ordner_id)='$ordner_id'));

Vielen Dank für deine Hilfe

Grüße aus Braunschweig

Fabian

  1. Hallo!

    Meine Datenbank besteht aus drei Tabellen.

    Tabelle_A      Tabelle_B       Tabelle_C
    -stellen_id    -stellen_id     -ordner_id
    -text1         -ordner_id      -unternehmen_id
    -text2
    -text3

    Ich würde gern alle Spalten der Tabelle A ausgeben, wenn in Tabelle_C: $ordner_id = ordner_id AND $unternehmen_id = unternehmen_id

    SELECT a.stellen_id FROM a INNER JOIN b ON (a.stellen_id=b.stellen_id)
    INNER JOIN c ON (b.ordner_id=c.ordner_id) WHERE c.unternehmen_id=$unternehmen_id AND c.ordner_id=$ordner_id;

    Auf mein Posting hatte ich bereits eine Antwort bekommen, leider funktioniert diese Lösung jedoch nicht bei mir.

    Wieso eröffnest Du zum zweiten mal heute den ein Posting zum selben Thema.

    MfG, André Laugks

    1. Danke André,

      nun hat es endlich funktioniert.

      Ich sitze schon seit Stunden an diesem Problem und konnte einfach keine Lösung finden.

      Zu meinem alten Posting hatte ich bereits zwei Nachrichten geschrieben, doch hat niemand geantwortet. Daher habe ich noch einmal gepostet.

      Mit deiner Lösung habe ich nun endlich das Prinzip verstanden, wie die Joins funktionieren.

      Grüße aus Braunschweig

      Fabian

      1. Hallo!

        Zu meinem alten Posting hatte ich bereits zwei Nachrichten geschrieben, doch hat niemand geantwortet. Daher habe ich noch einmal gepostet.

        Vielleicht weil die Frage noch nicht von "allen" gelesen wurde? Gerade solche Aktionen machen das Forum sehr unübersichtlich.

        Ich hatte Deine Frage heute früh schon gelesen, hatte aber kein Trieb zu antworten. Spätestens heute Abend hätte ich es gemacht, wenn keine Antwort gekommen wäre. Andere hätten es sicherlich auch so gemacht.

        MfG, André Laugks

        1. Ok, dann weiß ich bescheid.

          Es ist nur etwas blöd, wenn man eine Antwort bekommt, mit der man wenig anfangen kann und der Antwortende sich nicht mehr meldet.

          Alle anderen User sehen dann den Thread und gehen davon aus, dass das Problem bereits behoben ist.

          Danke nochmal

          Grüße Fabian

          1. Hallo!

            Alle anderen User sehen dann den Thread und gehen davon aus, dass das Problem bereits behoben ist.

            Stefan Münz hat mal eine Statistik veröffentlicht, wie oft ein Posting angeschaut wird. Du brauchst mit Sicherheit keine Angst zu haben, daß sich keiner Dein Posting, selbt bei schon einer vorhandenen Antwort, nicht mehr anschaut.

            MfG, André Laugks

            1. Hallo André,

              ja wenn das so ist... man lernt ja nie aus!

              Darf ich dir in diesem Zusammenhang noch einmal eine kleine Frage stellen? (Ich bin PHP Neuling)

              Deine Lösung hat ja prima funktioniert.

              Mit der Select Anfrage habe ich nun eine Variable mit den abgefragten Inhalten bekommen. Ich weiß nicht wie die Inhalte genau gespeichert werden doch stelle ich mir das ungefähr so vor:
              ($varable A)
                 ID   TextA  TextB
                  1    ddf    dfdf
                  2    dgdg   dfd
                  3    dgd    dfd
                  4    dfd    dfd

              Eine zweite Abfrage liefert mir in einer anderen Tabelle die Werte
              ($variable b)
                 ID   TextC
                 1   dsfsfs
                 2   fsgdfg
                 3   fgfdg
                 4    fdfdg

              daraus würde ich gern das Array oder ähnliches machen:
              ($variable c)
                 ID TextA  TextB TextC
                  1  ddf    dfdf  dsfsfs
                 ..  ..      ..   ...

              Damit ich das ganze Ding in einer While Schleife ausgeben kann:
              while ($row = mysql_fetch_array($variable c))
              {
                $ID=$row["ID"];
                $text a = $row["text a"];
                $text b = $row["text b"];
                $text c = $row["text c"];
              }

              Ist das überhaupt mit den Variablen möglich oder muß ich diese erst in ein Array umwandeln und dieses dann irgendwie auslesen oder gibt es noch einen anderen, besseren Weg?

              Für eine Antwort wäre ich Dir, und allen anderen, die dieses Posting lesen, sehr dankbar.

              Grüße aus Braunschweig

              Fabian

              1. Moin!

                Mit der Select Anfrage habe ich nun eine Variable mit den abgefragten Inhalten bekommen. Ich weiß nicht wie die Inhalte genau gespeichert werden doch stelle ich mir das ungefähr so vor:
                ($varable A)
                   ID   TextA  TextB
                    1    ddf    dfdf
                    2    dgdg   dfd
                    3    dgd    dfd
                    4    dfd    dfd

                Eine zweite Abfrage liefert mir in einer anderen Tabelle die Werte
                ($variable b)
                   ID   TextC
                   1   dsfsfs
                   2   fsgdfg
                   3   fgfdg
                   4    fdfdg

                daraus würde ich gern das Array oder ähnliches machen:
                ($variable c)
                   ID TextA  TextB TextC
                    1  ddf    dfdf  dsfsfs
                   ..  ..      ..   ...

                Mach eine vernünftige SQL-Abfrage, dann mußt du hinterher nichts im PHP-Programm sortieren. ;)

                Tabellen verknüpft man mit einem JOIN. Eine relativ kurze, aber mit Beispielen gewürzte Doku gibts hier: http://www.little-idiot.de/mysql/mysql-118.html Da gucke ich auch immer rein, wenn's was zu verknüpfen gibt. ;)

                Aber zu deinem Problem:

                SELECT spaltenvona,spaltenvonb FROM tabellea LEFT JOIN tabelle b USING (id)

                Das liefert dir alle Zeilen in Tabelle A und die zugehörigen Zeilen in Tabelle B in EINER Zeile. Wenn du sicherstellen kannst, daß jede ID nur einmal vorkommt, aber in beiden Tabellen, dann entledigst du dich damit eines komplexeren Problems auf einfache Art. Datensortieren sollte die Datenbank, dazu ist sie schließlich da und (hoffentlich) optimiert.

                Deine einzelne WHILE-Schleife wird mit dem Ergebnis dann _direkt_ funktionieren. :)

                Sollten die ID-Spalten unterschiedliche Namen haben, wird das "USING (id)" nicht funktionieren. Dann benutze stattdessen "ON tabellea.id1 = tabelleb.id2".

                Ich hoffe, es hilft. Rückfragen gerne hier im Forum. :)

                - Sven Rautenberg

                1. Moin,

                  ich kann mich leider erst jetzt für Eure Hilfe bedanken. Die Abfrage hat dann doch geklappt, so dass ich keine Variablen addieren oder Arrays bilden mußte.
                  Das Problem ist dann nur noch, dass ich durch diese Art von Abfragen, sobald ich sie einmal modifizieren möchte, nicht mehr durchsteige.

                  Grüße und ein großes Dankeschön
                  aus Braunschweig

                  Fabian

                  $sql ="SELECT stellenanzeigen.int_titel, stellenanzeigen.int_beschreibung, stellenanzeigen.ref_code, zeitfunktion_stellenanzeigen.zeit_ende FROM stellenanzeigen, zeitfunktion_stellenanzeigen INNER JOIN stellen_id_ordner_id ON (stellenanzeigen.stellen_id=stellen_id_ordner_id.stellen_id)
                  INNER JOIN ordnerid_uid ON (stellen_id_ordner_id.ordner_id=ordnerid_uid.ordner_id) WHERE ((ordnerid_uid.uid='$UID') AND(ordnerid_uid.ordner_id='$s_ordner_id')AND (zeitfunktion_stellenanzeigen.stellen_id = stellen_id_ordner_id.stellen_id))

                  1. Hi Fabian,

                    Das Problem ist dann nur noch, dass ich durch diese Art von Abfragen,
                    sobald ich sie einmal modifizieren möchte, nicht mehr durchsteige.

                    hm - bei Deiner Notationsweise würde ich auch nicht mehr durchsteigen. ;-)

                    Ich formatiere diesen String mal ein bißchen um:

                    $sql =     'SELECT s.int_titel, s.int_beschreibung, s.ref_code, z.zeit_ende '
                         .       'FROM stellenanzeigen              as s, '
                         .            'zeitfunktion_stellenanzeigen as z '
                         . 'INNER JOIN stellen_id_ordner_id         as so ON (s.stellen_id = so.stellen_id) '
                         . 'INNER JOIN ordnerid_uid                 as o  ON (so.ordner_id = o.ordner_id) '
                         .      'WHERE (     (o.uid        = ' . $db_handle.quote($UID)           . ' '
                         .              'AND (o.ordner_id  = ' . $db_handle.quote($s_ordner_id)   . ' '
                         .              'AND (z.stellen_id = ' . $db_handle.quote('s.stellen_id') . '));';

                    (etwaige Syntaxfehler bitte wegdenken ;-)

                    Mit lokalen Alias-Namen für die Tabellen, sinnvoller Einrückung und der
                    richtigen JOIN-Variante wird der vorher erschreckende SQL-Lindwurm plötz-
                    lich ziemlich "handzahm".
                    Denn vermutlich kann man mit irgend einer der vielen JOIN-Varianten noch
                    die eine oder andere Klausel weg bekommen (wenn Du jeweils über gleich-
                    namige Spalten JOINst, dafür gibt es wohl eine eigene Bezeichnung ... ?).
                    Dein Statement geht also wahrscheinlich noch kürzer zu notieren.

                    Ach ja, Du darfst in Deinen Quelltext natürlich auch zu jeder dieser Zeilen
                    einen Perl-Kommentar schreiben, warum Du da was tun wolltest.
                    So ein SQL-Statement ist nämlich von der semantischen Komplexität vergleich-
                    bar mit einem Perl-Programm von vielen hundert Zeilen! Das sollte Dir eine
                    Menge Kommentar wert sein.

                    Das alles gehört zu einem guten Programmierstil.
                    Du schreibst Deinen Quelltext nur einmal, aber Du liest ihn immer wieder
                    (womöglich müssen das auch noch andere tun, weia!).
                    Also schreibe ihn so, daß es Dir Spaß macht, ihn auch nach einem Jahr
                    nochmal zu lesen. Du wirst sehen, auf die Dauer lohnt sich das.

                    Viele Grüße
                          Michael

                    1. Hallo André,

                      du hast mich nun überzeugt, dass ein Posting auch auf hinteren Reihen noch gelesen wird.

                      Danke Michael für deine Antwort,

                      dein SQL Statement sieht wirklich "handzahmer" aus. Als PHP Neuling waren mir die Spalten-Aliase noch nicht so geheuer, weil man dadurch ja noch ein Schritt weiter umdenken muß. Aber insgesamt muß ich sehen, läßt sich das Ganze dann besser nachvollziehen.

                      Von Perl habe ich überhaupt gar keine Ahnung. Ich bin froh, dass es mit PHP so langsam anfängt zu funzen...

                      Nach und nach wird mir PHP jedoch klarer zum Großen Teil deswegen, weil hier sehr viele fähige User ihr Wissen in guten und nach zu vollziehenden Antworten weitergeben.

                      Ich hoffe ich werde mich einmal revangieren können, wenn ich PHP etc. besser beherrsche.

                      Grüße aus Braunschweig
                      Fabian

              2. Hallo!

                Damit ich das ganze Ding in einer While Schleife ausgeben kann:
                while ($row = mysql_fetch_array($variable c))
                {
                  $ID=$row["ID"];
                  $text a = $row["text a"];
                  $text b = $row["text b"];
                  $text c = $row["text c"];
                }

                Ist das überhaupt mit den Variablen möglich oder muß ich diese erst in ein Array umwandeln und dieses dann irgendwie auslesen oder gibt es noch einen anderen, besseren Weg?

                Ja, Dein Beispiel ist schon richtig.

                SELECT spalte1, spalte2 FROM tabelle;

                while($row = mysql_fetch_array($result))
                  {
                     echo $row["spalte1"];
                     echo $row["spalte2"]:
                  }

                Du mußt also nicht noch die Daten in einem Array zwischenspeichern.

                mysql_fetch_array() liefert für jeden Datensatz ein assoziatives Array. Wurden alle Datensätze abgearbeitet, bekommt while ein FALSE geliefert und bricht ab.

                Ich hatte letztens zwei Projekt, dort benötigte ich die Daten an mehreren "Stellen". Dort habe ich mir zuerst die Daten in ein mehrdimensionalen Array geholt. Der Vorteil war, nicht noch einmal ein SELECT absetzen zu müßen.

                SELECT id, spalte1, spalte2 FROM tabelle;

                while($row = mysql_fetch_array($result))
                  {
                     $datensatz[$row["id"]] = array($row["spalte1"]], $row["spalte2"]]);
                  }

                Aus dem Array $datensatz habe ich mir die verschiedenen Datensätze geholt.

                Sven hat aber schon bemerkt, daß Du Dir die benötigten Datensätze schon richtig aus der Datenbank holst und nicht noch über PHP sortierst oder Datensätze entfernst aus dem Ergebnis.

                MfG, André Laugks

    2. Moin! ;)

      SELECT a.stellen_id FROM a INNER JOIN b ON (a.stellen_id=b.stellen_id)
      INNER JOIN c ON (b.ordner_id=c.ordner_id) WHERE c.unternehmen_id=$unternehmen_id AND c.ordner_id=$ordner_id;

      Jetzt frage ich mich aber, warum phpMyAdmin und MySQL mit dieser Abfrage Probleme machen.

      "MySQL said: You have an error in your SQL syntax near 'INNER JOIN tab2 AS b ON (a.stellen_id=b.stellen_id) INNER JOIN tab3 AS c ON (b.o' at line 1"

      Mit LEFT JOIN anstatt INNER JOIN (was in meinem MySQL-Handbuch auch garnicht drinsteht) gehts dann nämlich prima.

      Fragen über Fragen... :)

      - Sven Rautenberg

      1. Hallo!

        Jetzt frage ich mich aber, warum phpMyAdmin und MySQL mit dieser Abfrage Probleme machen.

        Das kann ich Dir nicht beantworten. Meine MySQL mag diese Abfrage, Version 3.32.4*! Ich vermute mal ein Versionsproblem.

        "MySQL said: You have an error in your SQL syntax near 'INNER JOIN tab2 AS b ON (a.stellen_id=b.stellen_id) INNER JOIN tab3 AS c ON (b.o' at line 1"

        Mit LEFT JOIN anstatt INNER JOIN (was in meinem MySQL-Handbuch auch garnicht drinsteht) gehts dann nämlich prima.

        Fragen über Fragen... :)

        INNER JOIN ist MySQL ab neueren Versionen bekannt, glaube seit Version 3.32.2*, LEFT JOIN schon seite Version 3.22.*.

        Deshalb auch: "... near 'INNER JOIN ... "

        Hole Dir mal mit SELECT VERSION(); die Version.

        MfG, André Laugks

        1. Re-Moin!

          Jetzt frage ich mich aber, warum phpMyAdmin und MySQL mit dieser Abfrage Probleme machen.

          Das kann ich Dir nicht beantworten. Meine MySQL mag diese Abfrage, Version 3.32.4*! Ich vermute mal ein Versionsproblem.

          Scheint wohl so. Ich hab nur 'MySQL 3.22.32 running on localhost'. Das war halt dabei bei SuSE Linux 6.4 (?). ;)

          INNER JOIN ist MySQL ab neueren Versionen bekannt, glaube seit Version 3.32.2*, LEFT JOIN schon seite Version 3.22.*.

          Deshalb auch: "... near 'INNER JOIN ... "

          Tja, das ist natürlich hinderlich.

          Es hilft also immer sehr, auch phpMyAdmin auf dem fraglichen Server installiert zu haben, um in einer debugging-freundlichen Umgebung SQL-Abfragen auszuprobieren. :)

          - Sven Rautenberg

        2. Hi André,

          INNER JOIN ist MySQL ab neueren Versionen bekannt, glaube seit
          Version 3.32.2*, LEFT JOIN schon seite Version 3.22.*.

          nur so für's Archiv: können wir uns vielleicht auf 3.23 (statt 3.32) einigen? ;-)

          Aktuell ist 3.23.47; an 4.0alpha wird derzeit gestrickt. 3.32 dürfte es also vermutlich niemals geben.

          Viele Grüße
                Michael
          (mit 3.23.38 im Einsatz)