SorgenkindMech: MYSQL JOINs treiben mich in den wahnsinn ...

Hallo liebe Forum,

ich stecke (mal wieder) fest. ich versuche mich an einem JOIN über 3 tabellen

hier mal eine vereinfachte form:

tabelle1: mitarbeiter (id, vorname, name, gruppen_id, aktiv)
tabelle2: gruppenzugehörigkeit (id, gruppen_id, mitarbeiter_id)
tabelle3: gruppen (id, name, aktiv)

nun habe ich folgende abfrage:
SELECT gruppen.id as gruppen_id, gruppen.name as gruppen_name, mitarbeiter.gruppen_id, mitarbeiter.id as mitarbeiter_id, CONCAT(mitarbeiter.name,', ', mitarbeiter.vorname) as c_mitarbeiter FROM mitarbeiter, gruppen, gruppenzugehörigkeit WHERE gruppen.aktiv=1 AND gruppenzugehörigkeit.mitarbeiter_id=mitarbeiter.id AND gruppenzugehörigkeit gruppen_id=sub.id AND mitarbeiter.aktiv=1 ORDER by c_mitarbeiter ASC

das tut leider nicht was ich möchte

ich möchte alle mitabeiter, welche aktiv sind und einer aktiven gruppe zugehörig sind

für die meisten funktioniert das auch ganz gut, aber bei einem ist mir aufgefallen, dass dieser mehreren gruppen zugeordnet ist, einer inaktiven und einer aktiven. dieser ist entsprechend nicht im ergebnis enthalten.

weiß jemand wo mein fehler liegt?

Daaaaaaanke ;)

LG das SorgenkindMech

PS: die namen etc sind beispiele, also bitte den umlaut ignorieren ;)

  1. Moin!

    hier mal eine vereinfachte form:

    tabelle1: mitarbeiter (id, vorname, name, gruppen_id, aktiv)
    tabelle2: gruppenzugehörigkeit (id, gruppen_id, mitarbeiter_id)
    tabelle3: gruppen (id, name, aktiv)

    Das hat mit deinem Problem jetzt zwar gar nichts zu tun, aber eine der Grundsatzregeln, die ich für mich mal aufgestellt habe: Gleiches heißt überall gleich.

    Und für MySQL heißt das: Die ID-Spalte, die den primären Index darstellt, heißt überall gleich. Da sie in Fremdtabellen gerne als "tabellenname_id" benannt wird, um zu signalisieren, woher diese ID stammt, heißt sie in der Tabelle, wo sie herkommt, eben auch "tabellenname_id", und nicht nur "id".

    Vorteile:

    • In Querys, bei denen man mehr als eine Tabelle involviert und Id-Spalten benötigt, spart man sich das Vergeben von Alias-Namen, denn die Id-Spalten heißen schon individuell, und nicht alle identisch "Id".

    • Egal wo so eine Id-Spalte auftritt: Wenn irgendwo anders derselbe Name auch auftritt, ist klar, dass diese beiden Spalten dieselbe Id enthalten. Einträge derselben Id gehören zusammen.

    • In Joins kann man es sich sehr leicht machen, indem man "FROM tabellea JOIN tabelleb USING (mitarbeiter_id)" schreibt, und schon ist die Identität der Id im Join gewährleistet. Sowas funktioniert nur bei identischen Spaltennamen in beiden Tabellen, aber es bietet sich für 1:n-Beziehungen geradezu an.

    Und da kommen wir dann doch langsam zu deinem Join: Warum joinst du nicht explizit? Warum wirfst du erstmal alle drei Tabellen hinter FROM auf einen großen Haufen und sortierst dann die dir genehmen Join-Bedingungen und Selektionskriterien in einem riesigen WHERE?

    Trenne diese beiden Dinge. Im expliziten JOIN formulierst du, welche Zeilen der Tabellen zueinander gehören. Im unabhängig davon formulierten WHERE steht, welche der aus dem JOIN resultierenden Ergebniszeilen du als Resultat wünschst.

    Vorteil: Das WHERE kann man dann einfach komplett weglassen, um zu erfahren, aus welcher Ergebnismenge man eigentlich selektiert. Das geht bei deinem Mischmasch-WHERE-JOIN nicht.

    Also räume erstmal deinen Query auf, das erleichtert dir die Fehlersuche - und die beginnt schon mal ganz zu Anfang: Was ist das Ergebnis des JOINs der ersten beiden Tabellen? Was ist dann das Ergebnis mit der dritten Tabelle? Und welche Spalten enthalten dann die entscheidende Information?

    - Sven Rautenberg

    1. Moin!

      Huhu Sven!

      hier mal eine vereinfachte form:

      tabelle1: mitarbeiter (id, vorname, name, gruppen_id, aktiv)
      tabelle2: gruppenzugehörigkeit (id, gruppen_id, mitarbeiter_id)
      tabelle3: gruppen (id, name, aktiv)

      Das hat mit deinem Problem jetzt zwar gar nichts zu tun, aber eine der Grundsatzregeln, die ich für mich mal aufgestellt habe: Gleiches heißt überall gleich.

      Und für MySQL heißt das: Die ID-Spalte, die den primären Index darstellt, heißt überall gleich. Da sie in Fremdtabellen gerne als "tabellenname_id" benannt wird, um zu signalisieren, woher diese ID stammt, heißt sie in der Tabelle, wo sie herkommt, eben auch "tabellenname_id", und nicht nur "id".

      da bin ich absolut deiner meinung, auch wenn ich mich bisher nicht immer explizit daran gehalten habe

      Also räume erstmal deinen Query auf, das erleichtert dir die Fehlersuche - und die beginnt schon mal ganz zu Anfang: Was ist das Ergebnis des JOINs der ersten beiden Tabellen? Was ist dann das Ergebnis mit der dritten Tabelle? Und welche Spalten enthalten dann die entscheidende Information?

      • Sven Rautenberg

      Danke erstmal, ich hab echt den Wald vor lauter Bäumen nicht mehr gesehen. Logisch, dass man erstmal die Teilergebnisse überprüft ... oh man ...

      Das Ergebnis: Der fehlende Eintrag ist in jedem Teilergenis, sowie auch im Gesamtergebnis enthalten, mein Fehler war, und das ist echt beschäment, dass ich in der Browsersuche (STRG+F) heut Vormittag mal den Haken gesetzt hatte, dass Groß- und Kleinschreibung beachtet werden soll, da ich den Mitarbeiter immer klein schreibe dachte ich, er wäre nicht vorhanden ... omg ist das peinlich

      aber ich danke dir dennoch, nach über 1 Stunde suchen kann ich jetzt weiter machen ;)

      LG euer SorgenkindMech

      1. Sortierung über einen zusammengesetzten Wert erscheint mir Suboptimal.
        Warum nicht: ORDER BY mitarbeiter.name ASC, mitarbeiter.vorname ASC