Enigma: Komplizierte SQL-Syntax umändern

Hallo.

in meinem Board (PunBB) habe ich das Plugin EasyPoll installiert, welches uns die Möglichkeit gibt, Abstimmungen einzustellen (Ja/Nein, Multiumfrage usw).
Das ganze Plugin funktioniert so, dass über dem Thread die Abstimmungsmaske (oder, wenn man schon abgestimmt hat, die Ergebnisse) sieht. Doch das nur, wenn man erst auf das entsprechende Forum und dann auf die Umfrage-Topic klickt. Denn nur dort wird auf die Datei viewpoll.php verwiesen.
Auf der Startseite des Boards steht zu jedem Forum der zuletzt geschriebenen Beitrag in der Form "Am XX.XX.XXXX von USER_BLA" als Link. Dieser Link jedoch verweist auf die Datei viewtopic.php, die keine Umfrage-Eingabemaske oberhalb des Threads einfügt.
Unglücklicherweise klicken alle Benutzer meines Boards immer auf diesen Link und sehen somit nicht, dass man darin abstimmen kann/soll.

Ich habe mich also im Quelltext der index.php umgeschaut und bin auf folgende (für mich viel zu komplizierte) SQL-Anweisung gestoßen:

  
SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.forum_desc, f.redirect_url, f.moderators, f.num_topics, f.num_posts, f.last_post, f.last_post_id, f.last_poster  
FROM forum2_categories AS c  
INNER JOIN forum2_forums AS f ON c.id=f.cat_id  
LEFT JOIN forum2_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=1)  
WHERE fp.read_forum IS NULL OR fp.read_forum=1  
ORDER BY c.disp_position, c.id, f.disp_position  

Aus dem result dieser SQL-Abfrage wird die Startseite aufgebaut.
Das Einzige, was ich darin ändern möchte, ist, dass das Feld "question" aus der Tabelle forum2_topics hinten anfügen. Dieses ist leer, wenn die Topic keine Umfrage ist. Danach werde ich noch eine if-Abfrage ausführen, und demnach den Link abändern (von viewtopic.php auf viewpoll.php, mitsamt den GET-Parametern). Die Stelle habe ich schon gefunden, ich muss nun nur noch die SQL-Anweisung abändern.

Vorhin habe ich ein Tutorial zu Join durchgemacht, weil ich dieses bisher noch nicht beherrschte. Leider reichen mir diese Kenntnisse nicht, um hier einfach so ein weiteres Feld einzufügen. Versucht habe ich es schon, aber es kam niemals das raus, was ich wollte. Meistens verursachte ich sowieso Fehler...

Könnt ihr mir dabei helfen?
Ich bin Administrator des Boards und habe vollen Zugriff auf die Tabellen und auf den Quelltext.

Ich hoffe, ihr habt (bei dem langen Beitrag) auch verstanden, was ich machen möchte.

Viele Grüße
Enigma

  1. Hello,

    erster Schritt: Klammern setzen
    zweiter Schritt: prüfen, ob es immer noch genauso funktioniert
    dritter Schritt: die gewünschten Veränderungen in einem AND oder OR Zweig einbauen...

    Harzliche Grüße vom Berg
    http://www.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau

    1. Hi

      erster Schritt: Klammern setzen

      Wo soll ich Klammern setzen? Und wozu?

      Danke für deine schnelle Antwort
      Enigma

      1. erster Schritt: Klammern setzen
        Wo soll ich Klammern setzen? Und wozu?

        vergiss es...

        1. Hello,

          vergiss es...

          Wieso?

          Harzliche Grüße vom Berg
          http://www.annerschbarrich.de

          Tom

          --
          Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
          Nur selber lernen macht schlau

          1. War nur ein Hinweis an den Fragenden sich nicht primär mit der Klammersetzung zu befassen, die Frage hatte eine andere, äh, Basis.

            1. Hello,

              War nur ein Hinweis an den Fragenden sich nicht primär mit der Klammersetzung zu befassen, die Frage hatte eine andere, äh, Basis.

              Aber anhand der von Dir durchgeführten Strukturierung (formatierten Darstellung) des Queries konnte er doch auch schon eine Menge erkennen. Der nächste Schritt wäre dann, die logische Bindung der Stetements kenntlicher zu machen, eben durch Klammerstetzung.

              Selbstverständlich sind diese Klammern für geeübte SQL-Freaks unnötig, ber sie verdeutlichen ziemlich gut, was wann in welcher Reihenfolge ausgeführt wird. Manchmal wundert man sich dann, dass es mit Klammern ganznanders funktioniert, als ohne. Dann hat men seinen Fehler i.d.R. gefunden.

              Harzliche Grüße vom Berg
              http://www.annerschbarrich.de

              Tom

              --
              Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
              Nur selber lernen macht schlau

              1. Der will in seine Query irgendwie ein Datenfeld einer anderen bisher noch nicht refernzierten Tabelle quetschen, wird wohl ne üble Quälerei werden - so ganz ohne SQL-Kenntnisse...

                1. ... wird wohl ne üble Quälerei werden - so ganz ohne SQL-Kenntnisse...

                  Hab ich nicht gesagt. Ich arbeite schon länger mit PHP und MySQL, das einzige wichtige was ich von Mysql noch nicht konnte sind die Joins (und bei Anblick diesen SQLs brauch ich da schon einige Zeit dazu)

                  1. ... wird wohl ne üble Quälerei werden - so ganz ohne SQL-Kenntnisse...

                    Hab ich nicht gesagt. Ich arbeite schon länger mit PHP und MySQL, das einzige wichtige was ich von Mysql noch nicht konnte sind die Joins (und bei Anblick diesen SQLs brauch ich da schon einige Zeit dazu)

                    "Ganz ohne richtige SQL-Kenntnisse" war natürlich gemeint.   ;)

                    Mach doch einfach mal ein JOIN-Training, 120 Minuten sollten reichen. Dann einfach noch die Tabelle hinzuJOINen und das Datenfeld in die SELECT-Auflistung aufnehmen. (Aber - wie bereits geschrieben - ebenfalls die ggf. nur logische Verzeigerung zwischen den Tabellen verstehen bzw. zu verstehen suchen.)

              2. Hello,

                ups

                soviele Tippfehler habe ich aber gar nicht gemacht...
                Wer hat die da hineingemogelt?
                Ist schon wieder 1. April?

                Harzliche Grüße vom Berg
                http://www.annerschbarrich.de

                Tom

                --
                Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                Nur selber lernen macht schlau

  2. Erst mal den Code ein wenig trimmen:

      
    SELECT  
     c.id AS cid,  
     c.cat_name,  
     f.id AS fid,  
     f.forum_name,  
     f.forum_desc,  
     f.redirect_url,  
     f.moderators,  
     f.num_topics,  
     f.num_posts,  
     f.last_post,  
     f.last_post_id,  
     f.last_poster  
    FROM  
     forum2_categories AS c  
    INNER JOIN  
     forum2_forums AS f ON (c.id=f.cat_id)  
    LEFT JOIN  
     forum2_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=1)  
    WHERE  
     (fp.read_forum IS NULL) OR  
     (fp.read_forum=1)  
    ORDER BY  
     c.disp_position ASC,  
     c.id ASC,  
     f.disp_position ASC  
    
    

    Das Einzige, was ich darin ändern möchte, ist, dass das Feld "question" aus der Tabelle forum2_topics hinten anfügen.

    Die Tabelle 'forum2_topics' ist in oben aufgeführter Abfrage nicht refernziert, also gehts nicht o.w..
    Erst mal die Beziehungsart und deren Implementation der o.g. Tabelle erläutern. Ggf. das gesamte Tabellendesign der involvierten tabellen offenlegen.

  3. yo,

    Das Einzige, was ich darin ändern möchte, ist, dass das Feld "question" aus der Tabelle forum2_topics hinten anfügen.

    king schnully hat es schon angesprochen, entscheident ist, wie die tabelle forum2_topics mit den anderen tabellen verbunden ist. wenn wir das wissen, dann ist das sql-statement kein problem mehr. aber diese info musst du versuchen für "uns" herauszubekommen, damit wir dir die abfrage schreiben können.

    eine methode wäre, du suchst nach der tabelle im quell-code, ob es da nicht eventuell schon andere sql-anweisungen gibt, es der wir rückschlüsse ziehen können.

    eine andere methode wäre, dass du uns schreibst, welche spaltennamen die tabelle besitzt. mit ein wenig glück, können wir von den namen auf die verbindung schließen.

    Ilja

    1. Hi

      king schnully hat es schon angesprochen, entscheident ist, wie die tabelle forum2_topics mit den anderen tabellen verbunden ist. wenn wir das wissen, dann ist das sql-statement kein problem mehr. aber diese info musst du versuchen für "uns" herauszubekommen, damit wir dir die abfrage schreiben können.

      Das geeignetste Verbindungsglied habe ich gefunden: Das Feld f.id (=> fid) gibt es auch in der forum2_topic und heißt dort "forum_id" (das Feld enthält die ID des Forums, in der die Topic sich befindet).
      Zwei andere Verbindungsglieder wären auch denkbar:
      f.last_post_id <=> last_post_id (ID des letzten Posts)
      f.last_post <=> last_post (Unix-Zeit des letzten Beitrags)

      (alles nach dem <=> ist der Spaltenname in der forum2_topics)

      eine methode wäre, du suchst nach der tabelle im quell-code, ob es da nicht eventuell schon andere sql-anweisungen gibt, es der wir rückschlüsse ziehen können.

      Das Board wurde auf Schnelligkeit getrimmt, weitere SQL-Abfragen gibt es (zumindest in der index.php) nicht.

      eine andere methode wäre, dass du uns schreibst, welche spaltennamen die tabelle besitzt. mit ein wenig glück, können wir von den namen auf die verbindung schließen.

      Zur Sicherheit mache ich das auch, als Screenshot aber:

      Das hier ist die Struktur von forum2_topics:
      http://img129.imageshack.us/img129/4204/phpmyadminzf8.jpg

      Und das hier sind die Felder aus dem Ergebnis der komplizierten SQL-Abfrage:
      http://img129.imageshack.us/img129/4514/phpmyadmin1bd1.jpg

      Seht ihr eine bessere Möglichkeit, beide Tabellen miteinander zu verbinden?

      Vielen Dank
      Enigma

      1. yo,

        Zwei andere Verbindungsglieder wären auch denkbar:
        f.last_post_id <=> last_post_id (ID des letzten Posts)
        f.last_post <=> last_post (Unix-Zeit des letzten Beitrags)

        last_post und last_post_id scheinen zwei selbstreferenzen auf die eigene tabelle forum2_topic zu sein. ich vermute mal, da stehen die daten drinne, die dann auch als link auf der startseite angezeigt werden. aber dann sollte auch eine entsprechende abfrage auf der startseite sein, die diese informationen ausliesst, kannst du so eine finden ? insofern bin ich mir nicht ganz sicher, ob wir an der richtigen abfrage herumbasteln.

        aber schauen wir mal und ergänzen die abfrage. wichtig dabei ist, wenn wir eine neue tabelle hinzufügen, dann kann sich auch die anzahl der ergebnis-datensätze verändern. oder mit anderen worten, ein forum hat meistens mehrere topics. das könnte eventuell zu einem problem führen, dass man beachten muss.

        das erste was wir machen, wir fügen die weitere tabelle einfach in die abfrage mit ein und zwar als OUTER JOIN, kann ja sein, dass das forum noch gar keine beiträge hat.

        SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.forum_desc, f.redirect_url, f.moderators, f.num_topics, f.num_posts, f.last_post, f.last_post_id, f.last_poster, question
        FROM forum2_categories AS c
        INNER JOIN forum2_forums AS f ON c.id=f.cat_id
        LEFT JOIN forum2_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=1)
        LEFT JOIN forum2_topics ON t (t.forum_id = f.id)
        WHERE fp.read_forum IS NULL OR fp.read_forum=1
        ORDER BY c.disp_position, c.id, f.disp_position

        wie gesagt vermute ich, dass du bei dieser abfrage wesentlich mehr datensätze zurück bekommst. insofern kannst du auch folgendes probieren.

        SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.forum_desc, f.redirect_url, f.moderators, f.num_topics, f.num_posts, f.last_post, f.last_post_id, f.last_poster, question
        FROM forum2_categories AS c
        INNER JOIN forum2_forums AS f ON c.id=f.cat_id
        LEFT JOIN forum2_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=1)
        LEFT JOIN forum2_topics ON t (t.last_post_id = f.id)
        WHERE fp.read_forum IS NULL OR fp.read_forum=1
        ORDER BY c.disp_position, c.id, f.disp_position

        oder eine zweite abfrage einbauen.

        SELECT last_post, last_post_id, last_poster, question
        FROM forum2_topics

        schau mal, ob du damit was anfangen kannst.

        Ilja

        1. Hi

          Zwei andere Verbindungsglieder wären auch denkbar:
          f.last_post_id <=> last_post_id (ID des letzten Posts)
          f.last_post <=> last_post (Unix-Zeit des letzten Beitrags)

          last_post und last_post_id scheinen zwei selbstreferenzen auf die eigene tabelle forum2_topic zu sein. ich vermute mal, da stehen die daten drinne, die dann auch als link auf der startseite angezeigt werden.

          Richtig.

          aber dann sollte auch eine entsprechende abfrage auf der startseite sein, die diese informationen ausliesst, kannst du so eine finden ?

          Wenn man einen neuen Beitrag in eine Topic schreibt, wird in die Tabelle "forum2_topics" und in "forum2_forums" die Felder "last_post_id", "last_post" und "last_poster" upgedated.
          Der SQL (aus meinem OP) liest aber die Daten aus forum2_forums aus, und diese stellt er dann dar.

          das erste was wir machen, wir fügen die weitere tabelle einfach in die abfrage mit ein und zwar als OUTER JOIN, kann ja sein, dass das forum noch gar keine beiträge hat.

          SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.forum_desc, f.redirect_url, f.moderators, f.num_topics, f.num_posts, f.last_post, f.last_post_id, f.last_poster, question
          FROM forum2_categories AS c
          INNER JOIN forum2_forums AS f ON c.id=f.cat_id
          LEFT JOIN forum2_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=1)
          LEFT JOIN forum2_topics ON t (t.forum_id = f.id)
          WHERE fp.read_forum IS NULL OR fp.read_forum=1
          ORDER BY c.disp_position, c.id, f.disp_position

          Und wo ist hier der OUTER JOIN?
          Na gut, also, deine beiden SQLs geben mir dieselbe Fehlermeldung zurück: "Unknown column 't.last_post_id' in 'on clause'".

          oder eine zweite abfrage einbauen.

          SELECT last_post, last_post_id, last_poster, question
          FROM forum2_topics

          Wäre halt geschickter, wenn ic das in den einen SQL einfügen könnte. Wenn aber alle Stricke reißen, hätte ich das aber so gemacht.

          Viele Grüße
          Enigma

          1. yo,

            Wenn man einen neuen Beitrag in eine Topic schreibt, wird in die Tabelle "forum2_topics" und in "forum2_forums" die Felder "last_post_id", "last_post" und "last_poster" upgedated.
            Der SQL (aus meinem OP) liest aber die Daten aus forum2_forums aus, und diese stellt er dann dar.

            ahh ok, die tabelle forum2_forums hat also auch eine selbstreferenz. die dient wohl dazu, den letzten beitrag eines topics zu speichern, die anderen die insgesamt letzten des forums.

            Und wo ist hier der OUTER JOIN?

            LEFT JOIN ist ein OUTER JOIN, genauso wie RIGHT JOIN einer ist.

            Na gut, also, deine beiden SQLs geben mir dieselbe Fehlermeldung zurück: "Unknown column 't.last_post_id' in 'on clause'".

            das liegt daran, dass ich mich verschrieben habe und den alias namen für die tabelle hinter die ON klausel geschirben habe, er gehört aber davor, also:

            LEFT JOIN forum2_topics t ON (t.forum_id = f.id)
            bzw. LEFT JOIN forum2_topics t ON (t.last_post_id = f.id)

            zweiteres sollte dir die richtige anzahl von ergebnis-datensätze liefern, die erste alle topics des forums.

            Ilja

            1. Hi Ilja und Rest des Forums,

              also, ich hab jetzt meinen SQL erweitert:

                
              SELECT c.id AS cid, c.cat_name, f.id AS fid, f.forum_name, f.forum_desc, f.redirect_url, f.moderators, f.num_topics, f.num_posts, f.last_post, f.last_post_id, f.last_poster, t.question, o.Id AS topic_id  
              FROM forum2_categories AS c  
              INNER JOIN forum2_forums AS f ON c.id = f.cat_id  
              LEFT JOIN forum2_forum_perms AS fp ON ( fp.forum_id = f.id  
              AND fp.group_id =1 )  
              LEFT JOIN forum2_topics t ON ( t.last_post_id = f.id )  
              LEFT JOIN forum2_topics o ON ( o.last_post_id = f.id )  
              WHERE fp.read_forum IS NULL  
              OR fp.read_forum =1  
              ORDER BY c.disp_position, c.id, f.disp_position  
              
              

              Also ich hab noch eine Zeile "topic_id" eingefügt (auch die brauche ich zum Aufbauen des neuen Links, wie ich hinterher festgestellt habe). In dieser Zeile soll die Topic-ID angezeigt werden (Feld "Id" in Tabelle forum2_topics), in der die Topic-ID der Topic, in die zuletzt geschrieben wurde, stehen soll.

              Dieser SQL erzeugt keine Fehler (Gott sei Dank).
              Doch er zeigt einfach in allen Datensätzen in den Feldern "question" und "topic_id" immer NULL an.
              Woran liegt das diesmal? Oder woran könnte es diesmal liegen?

              Gruß
              Enigma

              1. yo,

                LEFT JOIN forum2_topics t ON ( t.last_post_id = f.id )
                LEFT JOIN forum2_topics o ON ( o.last_post_id = f.id )

                hier bindest du 2 mal die tabelle forum2_topics ein, warum ist mir noch nicht ganz klar.

                Doch er zeigt einfach in allen Datensätzen in den Feldern "question" und "topic_id" immer NULL an.
                Woran liegt das diesmal? Oder woran könnte es diesmal liegen?

                kann ich so auf den ersten blick nicht sagen, eventuell sind die tabellen doch anders verknüpft als gedacht. aber wir können das problem ja mal eingrenzen. mach mal folgende zwei abfrage und schau, ob du datensätze bekommst und wenn ja welche.

                SELECT f.id AS fid, f.forum_name, f.forum_desc, f.redirect_url, f.moderators, f.num_topics, f.num_posts, f.last_post, f.last_post_id, f.last_poster, t.question
                FROM forum2_forums f
                INNER JOIN forum2_topics t ON t.last_post_id = f.id

                SELECT f.id AS fid, f.forum_name, f.forum_desc, f.redirect_url, f.moderators, f.num_topics, f.num_posts, f.last_post, f.last_post_id, f.last_poster, t.question
                FROM forum2_forums f
                INNER JOIN forum2_topics t ON t.forum_id = f.id

                Ilja