Kanalpirat: Probleme mit JOIN über mehrere Tabellen (mySQL)

Hallo Forum,

die JOINs bringen mich um den Verstand. Folgende Datenbank habe ich hier:

Tabelle kategorie:
ID | Name
---+-------
1  | Blume
2  | Baum

Tabelle rel_kat_grp:
katID | grpID
------+-------
1     | 4

Tabelle gruppe:
ID | Name
---+--------
4  | Monster

Tabelle rel_grp_ben:
grpID | benID
------+--------
4     | 9

Tabelle benutzer:
ID | Name
---+------
9  | Paul

Also, ein Gast darf nur die Kategorie Baum sehen. Paul ist ein Monster und darf Baum und Blume sehen.

Über WHERE-Bedingungen sieht ein Gast gar nichts und Paul nur Blume, weil es in der rel_kat_grp keinen Eintrag für Baum gibt:

  
SELECT kategorie.* FROM kategorie, rel_kat_grp, rel_grp_ben WHERE kategorie.ID = rel_kat_grp.katID AND rel_kat_grp.grpID = rel_grp_ben.grpID AND rel_grp_ben.benID = '9'

Über LEFT JOINs sehen alle alles, weil halt jeder Eintrag in kategorie im Ergebnis auftaucht:

  
SELECT kategorie.* FROM kategorie LEFT JOIN rel_kat_grp ON kategorie.ID = rel_kat_grp.katID LEFT JOIN rel_grp_ben ON rel_kat_grp.grpID = rel_grp_ben.grpID LEFT JOIN benutzer ON rel_grp_ben.benID = '9'

Wie muss ich WHERE und LEFT JOIN mischen?

Anwendung ist ein Menü für eine Homepage. Unangemeldete Besucher sollen nur betimmte Menüeinträge sehen (oben Baum), angemeldete zusätzlich die, die zu den Gruppen (oben Monster) gehören, in denen sie selbst sind.

Hoffentlich habt ihr mich verstanden. :-)

Danke euch!

  1. Mahlzeit Kanalpirat,

    SELECT kategorie.* FROM kategorie, rel_kat_grp, rel_grp_ben WHERE kategorie.ID = rel_kat_grp.katID AND rel_kat_grp.grpID = rel_grp_ben.grpID AND rel_grp_ben.benID = '9'

      
    Vermische nicht implizite und explizite JOIN-Syntax - auf keinen Fall innerhalb einer Abfrage, aber auch in unterschiedlichen Abfragen ist das meistens nicht sehr hilfreich.  
      
    ~~~sql
    SELECT kategorie.*  
      FROM kategorie  
      JOIN rel_kat_grp ON kategorie.ID = rel_kat_grp.katID  
      JOIN rel_grp_ben ON rel_kat_grp.grpID = rel_grp_ben.grpID  
     WHERE rel_grp_ben.benID = '9'
    

    BTW: Wieso ist eine ID ein alphanumerisches Feld?

    Grundsätzlich wären für Dich sicherlich die Artikel "Einführung in Joins" und "Fortgeschrittene Jointechniken" (in der Reihenfolge) interessant.

    MfG,
    EKKi

    --
    sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
    1. SELECT kategorie.*

      FROM kategorie
        JOIN rel_kat_grp ON kategorie.ID = rel_kat_grp.katID
        JOIN rel_grp_ben ON rel_kat_grp.grpID = rel_grp_ben.grpID
      WHERE rel_grp_ben.benID = '9'

        
      Das funktioniert leider nicht. Kategorien ohne Eintrag in rel\_kat\_grp werden nicht angezeigt.  
        
      
      > BTW: Wieso ist eine ID ein alphanumerisches Feld?  
        
      Ist es nicht, die 9 ist bei mir natürlich eine Variable, und ohne '' bekomme ich beim Aufruf von mysql\_fetch\_assoc() die Warnung mysql\_fetch\_assoc(): supplied argument is not a valid MySQL result resource.  
        
      
      > Grundsätzlich wären für Dich sicherlich die Artikel "[Einführung in Joins](http://aktuell.de.selfhtml.org/artikel/datenbanken/joins/)" und "[Fortgeschrittene Jointechniken](http://aktuell.de.selfhtml.org/artikel/datenbanken/fortgeschrittene-joins/)" (in der Reihenfolge) interessant.  
        
      Die habe ich schon gelesen, leider ohne Erfolg. Ich muss mir da mal einen Tag Zeit für nehmen. :-)
      
      1. Mahlzeit Kanalpirat,

        Das funktioniert leider nicht. Kategorien ohne Eintrag in rel_kat_grp werden nicht angezeigt.

        Dann ist mir irgendwie noch nicht so ganz klar, wer wann was warum sehen darf und was nicht. Versuche bitte, das *OHNE* irgendwelchen SQL-Code fachlich zu erklären ...

        BTW: Wieso ist eine ID ein alphanumerisches Feld?

        Ist es nicht, die 9 ist bei mir natürlich eine Variable, und ohne '' bekomme ich beim Aufruf von mysql_fetch_assoc() die Warnung mysql_fetch_assoc(): supplied argument is not a valid MySQL result resource.

        Das bedeutet (vermutlich) nur, dass die Abfrage fehlerhaft war und deshalb mittels mysql_fetch_assoc() nicht auf irgendeine Ergebnismenge zugegriffen werden kann. Du hast vergessen, dass mysql_query() einen Rückgabewert liefert, und nicht auf diesen überprüft. Weiterhin hast Du vergessen, den entsprechenden von der der Datenbank gelieferten Fehlertext abzufragen.

        Die habe ich schon gelesen, leider ohne Erfolg. Ich muss mir da mal einen Tag Zeit für nehmen. :-)

        Ja.

        MfG,
        EKKi

        --
        sh:( fo:| ch:? rl:( br:> n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
        1. Dann ist mir irgendwie noch nicht so ganz klar, wer wann was warum sehen darf und was nicht. Versuche bitte, das *OHNE* irgendwelchen SQL-Code fachlich zu erklären ...

          Ausgangspunkt ist die Menüstruktur, die aus der Tabelle kategorie dynamisch erzeugt wird. Beispiel:

          Aktuelles
            Wichtiges
            Internes
          Tiere
            Vögel
            Bären
          Pflanzen
            Blumen

          Der Menüpunkte Internes soll aber nur sichtbar sein, wenn man sich angemeldet hat. Für Internes existiert also ein Eintrag in rel_kat_grp so wie es eine dazugehörige Gruppe gibt, in der alle Benutzer aufgeführt sind, die diesen Menüpunkt sehen dürfen. (Es gibt im Endausbau etwa 150 Benutzer und 30 Gruppen)

          Für benutzer.ID = 0 (keine Anmeldung) brauche ich also alle kategorie-Einträge, für die es *keinen* Eintrag in rel_kat_grp gibt, für alle anderen Fälle zusätzlich die Kategorien, die von den Gruppen, zu denen der Benutzer gehört, gesehen werden dürfen.

          Das bedeutet (vermutlich) nur, dass die Abfrage fehlerhaft war und deshalb mittels mysql_fetch_assoc() nicht auf irgendeine Ergebnismenge zugegriffen werden kann. [...]

          Alles klar, den Fehler habe ich ausgemerzt. Die Variable war NULL, wenn sich niemand angemeldet hatte. Jetzt ist sie 0. :-)

  2. yo,

    die JOINs bringen mich um den Verstand.

    das problem ist ein anderes, wo ist den persistiert, dass Blume jeder sehen darf und Baum nicht ? alleine mit den joins bekommt man das meiner meinung nach nicht hin, weil die inner joins eben nicht "public" abbilden können. und wenn du outer joins benutzt, dann kannst du nicht "private" abbilden.

    Ilja

    1. das problem ist ein anderes, wo ist den persistiert, dass Blume jeder sehen darf und Baum nicht ? alleine mit den joins bekommt man das meiner meinung nach nicht hin, weil die inner joins eben nicht "public" abbilden können. und wenn du outer joins benutzt, dann kannst du nicht "private" abbilden.

      Genau. Na gut, dann werde ich wohl eine Gruppe "Alle" anlegen müssen und für jeden Eintrag in kategorie auch einen in rel_kat_grp anlegen. Dann hab ich gleich die Möglichkeit, einzelen Kategorien für alles auszublenden, vielleicht gar nicht schlecht.

      Danke euch!