Join mit mehreren Spalten

  • SQL

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von Niko Ortner.

    Join mit mehreren Spalten

    Moinsen,

    wir haben eine Datenbankstruktur erstellt (im Anhang).

    Die Tabelle tbl_raeume hat mehrere Fremdschlüssel (Zuständigkeit, Verantwortlicher, Funktion).
    Wir möchten jetzt eine SQL Abfrage basteln die uns nicht die Fremdschlüssel ID´s ausgibt, sondern deren Primärwert in der jeweiligen Tabelle.
    Unser erster Ansatz war folgender:

    SQL-Abfrage

    1. ​SELECT Rae_Raumnummer, Le_Kuerzel FROM tbl_Lehrer JOIN tbl_Raeume ON Le_ID= Rae_Zustaendigkeit WHERE Le_ID = '......'


    Das Ergebnis davon ist in der Capture.PNG zu finden. Wir brauchen allerdings noch mehr Spalten (Verantwortlicher und Funktion). Diese könnten wir einfach dazu schreiben, jedoch wollen wir nicht die ID´s sondern deren Primärwert.

    Ich hoffe ihr wisst was gemeint ist.

    Danke im Voraus
    Bilder
    • b708aa90b2176161bb937bd6e9660ac3.png

      52,56 kB, 1.152×586, 135 mal angesehen
    • Capture.PNG

      14,28 kB, 237×319, 116 mal angesehen
    Erst mal möchte ich anmerken, dass das Datenbankmodell ziemlich vermurkst ist. Ich würde grundsätzlich von Deutsch abraten (und stattdessen Englisch verwenden), aber wenn es schon sein muss, dann sollte man wenigstens keine Umlaute verwenden. Aber noch viel schlimmer ist es, zu mischen: tbl_LehrerRäume aber tbl_Raeume. Warum sind Spalten am Anfang groß geschrieben, Tabellen aber klein?
    Und warum stehen bei allen Spaltennamen nochmal Tabellenkürzel davor? Es ist ja sowieso klar, welche Spalte zu welcher Tabelle gehört. Und wenn es doch mal Mehrdeutigkeiten gibt (weil man z.B. mehrere IDs hat) kann man immer noch den Tabellennamen davorschreiben und ein Alias verwenden (SELECT Teacher.Id AS Teacher_Id, ... FROM ...).
    Es wird viel darüber gestritten, ob Tabellen im Sigular oder Plural benannt werden sollten; ich bin für Singular.

    Wir möchten jetzt eine SQL Abfrage basteln die uns nicht die Fremdschlüssel ID´s ausgibt, sondern deren Primärwert in der jeweiligen Tabelle.

    Wie es genau geht, hängt von den jeweiligen Tabellen ab, und was Du erreichen möchtest.
    Anhand der Beispiel-Query gehe ich davon aus, dass Du sowas haben möchtest:

    Brainfuck-Quellcode

    1. |--------|----------|
    2. | Raum | Lehrer |
    3. |--------|----------|
    4. | Raum 1 | Lehrer 1 |
    5. | Raum 2 | Lehrer 1 |
    6. | Raum 2 | Lehrer 2 |
    7. | Raum 2 | Lehrer 3 |
    8. | Raum 3 | Lehrer 1 |
    9. | Raum 3 | Lehrer 2 |
    10. | Raum 4 | Lehrer 2 |
    11. | Raum 5 | Lehrer 2 |
    12. |--------|----------|
    Also jeder Raum kann von mehreren Lehreren verwendet werden und jeder Lehrer kann mehrere Räume verwenden. Es stellt sich aber die Frage, was passieren soll, wenn z.B. ein Lehrer keinen Raum verwendet. Oder wenn ein Raum von keinem Lehrer verwendet wird. Am sinnvollsten wäre aus meiner Sicht, wenn diese Einträge nicht in der Liste vorkommen.
    In diesem, konkreten Fall macht es Sinn, zuerst alles von der Zwischentabelle abzufragen und anschließend die anderen Tabellen "draufzujoinen".
    Also so:

    SQL-Abfrage

    1. SELECT *
    2. FROM Zwischentabelle
    3. LEFT JOIN Raum ON Zwischentabelle.FremdschlüsselAufRaum = Raum.Primärschlüssel
    4. LEFT JOIN Lehrer ON Zwischentabelle.FremdschlüsselAufLehrer = Lehrer.Primärschlüssel
    Das reicht, damit alle Infos vorhanden sind.
    Jetzt muss man nur noch die benötigten Spalten auswählen:

    SQL-Abfrage

    1. SELECT Raum.Nummer, Lehrer.Kürzel
    2. FROM Zwischentabelle
    3. LEFT JOIN Raum ON Zwischentabelle.FremdschlüsselAufRaum = Raum.Primärschlüssel
    4. LEFT JOIN Lehrer ON Zwischentabelle.FremdschlüsselAufLehrer = Lehrer.Primärschlüssel

    Das wäre dann, wenn man die Namen Deiner Datenbank einfügt das:

    SQL-Abfrage

    1. SELECT tbl_Raeume.Rae_Raumnummer, tbl_Lehrer.Le_Kuerzel
    2. FROM tbl_LehrerRäume
    3. LEFT JOIN tblRaeume ON tbl_LehrerRäume.Lr_Raum = tblRaeume.Rae_ID
    4. LEFT JOIN tblLehrer ON tbl_LehrerRäume.Lr_Lehrer = tblLehrer.Le_ID


    Wie gesagt: Was genau Du haben möchtest, musst Du wissen. Mir leuchtet jetzt z.B. nicht ein, warum Räume sowohl eine m:n-Relation zu Lehrern haben, aber auch eine n:1-Relation.

    Edit: Ja, klar, ich meinte natürlich Brainfuck-Code...
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    Niko Ortner schrieb:

    dass das Datenbankmodell ziemlich vermurkst ist
    Ja, die Benamung ist Grotte: Unnütze Prefixe erzeugen später Wort-Ungetüme im Code, und die Plural-Flexierung wird suggerieren, dass ein Datensatz eine Mehrzahl sei (was er aber genau nicht ist).


    Aber immerhin ergibt die Struktur doch einen Sinn, also wie die Relationen angelegt sind. :thumbup:

    Naja - vlt. auch nicht ganz. Mir ist jdfs. unklar, warum da ein Unterschied gemacht wird zw. "Verantwortlicher" und "Zuständiger".
    Und was diesen Unterschied inne Realität ausmacht (weil die wird ja modelliert).

    ErfinderDesRades schrieb:

    wird zw. "Verantwortlicher" und "Zuständiger".



    Will mein Lehrer so, ich weiß auch nicht warum. Ist eigentlich unnötig.
    Danke, werde morgen hier wieder schreiben ob es alles geklappt hat.
    Und ja, das Datenmodell ist von der Benamung schrott, haben das aber in der Datenbank schon alles abgeändert gehabt und haben dabei ganz vergessen die Struktur wieder anzupassen.
    Bei Lehrern reagier ich immer empfindlich...
    Also ich empfehle, sich nicht alles bieten zu lassen. Wenn der Unterschied dir nicht klar ist, dann soll er ihn dir erklären. Vlt. kommt dabei ja sogar raus, dasses da garkeinen Unterschied gibt - davon kriegst du bestimmt keine schlechte Note.

    Schlimm ist eben, wenn man unlogische Sachen sich bieten lässt, akzeptiert, und am Ende in seine Gewohnheiten übernimmt.
    Der Unterschied ist eigentlich "fast" bedeutungslos. Das Feld "Verantwortlicher" soll nur nur formell existieren. In Fokus gesetzt wird eigentlich nur der Zuständige Lehrer.

    ErfinderDesRades schrieb:

    am Ende in seine Gewohnheiten übernimmt.

    Ganz sicher nicht, von dem lass ich mir sowieso nichts mehr bieten. Ist auch das letzte "freiwillige" Projekt was ich für den mache. Warum das so ist, ist eine andere Geschichte die jetzt hier nicht relevant ist.
    ALSOOO:

    Mein Kumpel hat es gestern geschafft eine Abfrage zu erstellen die uns fast alles erledigt. Was noch fehlt ist die Spalte "Verantwortlicher".
    Unsere Abfrage sieht momentan so aus:

    SQL-Abfrage

    1. SELECT tbl_raeume.Raumnummer, tbl_lehrer.Kuerzel, tbl_funktionen.Name FROM tbl_raeume JOIN tbl_lehrer ON tbl_raeume.Zustaendigkeit = tbl_lehrer.ID AND tbl_lehrer.ID = 36 JOIN tbl_funktionen ON tbl_raeume.Funktion = tbl_funktionen.ID


    Unser Problem ist jetzt, dass sich Zustaendigkeit und Verantwortlicher gegenseitig behindern weil beide einen Fremdschlüssel auf "Kuerzel" haben. Wie können wir also die beiden unterscheiden? Ich hoffe es ist verständlich. Was wir jetzt also noch zusätzlich benötigen ist das Feld "Verantwortlicher" in Relation auf Kuerzel.
    JOIN tbl_lehrer ON tbl_raeume.Zustaendigkeit = tbl_lehrer.ID AND tbl_lehrer.ID = 36
    Bzw.
    JOIN Tabelle ON Spalte = Spalte = Wert
    Geht das überhaupt?

    Um eine Tabelle mehrmals zu Joinen kann man ihnen Aliase geben:

    SQL-Abfrage

    1. SELECT tbl_raeume.Raumnummer, Zuständiger.Kuerzel, Verantwortlicher.Kuerzel, tbl_funktionen.Name
    2. FROM tbl_raeume
    3. JOIN tbl_lehrer AS Zuständiger
    4. ON tbl_raeume.Zustaendigkeit = tbl_lehrer.ID AND tbl_lehrer.ID = 36
    5. LEFT JOIN Zwischentabelle
    6. ON tbl_raeume.ID = Zwischentabelle.FremdschlüsselAufRäume
    7. LEFT JOIN tbl_lehrer AS Verantwortlicher
    8. ON Zwischentabelle.FremdschlüsselAufLehrer = Verantwortlicher.ID
    9. JOIN tbl_funktionen
    10. ON tbl_raeume.Funktion = tbl_funktionen.ID

    Und ich würde Dir und Deinem Kollegen raten, Zeilenumbrüche zu verwenden. Das macht die Sache wesentlich besser lesbar.

    (Das ist übrigens nur Pseudocode. Du musst es noch anpassen.)
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils

    ErfinderDesRades schrieb:

    Aber warum machst du da immer Left Join s hin?


    Sollte ein Raum keinen... ääh... Verantwortlichen haben, kommt der Raum trotzdem im Ergebnis vor und die Spalten vom Verantwortlichen sind dann halt NULL, wenn ich das richtig im Kopf habe.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils