SQL SELECT-Abfrage über mehrere Tabellen mit optionalen Spalten - möglich?



  • Hallo

    ich befasse mich seit kurzem mit SQL (SQl Server 2005) und ASP.Net. Nun habe ich folgendes Problem: Ich habe zwei bzw. drei Tabellen, wobei eine der beiden Tabellen eine Link-Tabelle ist, die zwischen den beiden anderen Tabellen verknüpft. Ich habe also zwischen Tabelle A und C eine N:M Verbindung und dazu die Link-Tabelle B, die mir sagt wer zu wem in Relation steht. Nun folgendes: Ich möchte Spalten aus Tabelle A und Tabelle C abfragen. Das Problem ist, wenn ich das in einem Select mache, es aber in Tabelle C keine Daten gibt, dann ist auch in Tabelle B kein Link eingetragen und ich bekomme keine Ergebnisse, obwohl in Tabelle A Daten vorhanden wären, die ich trotzdem angezeigt haben möchte. Wie kann ich mein Select so gestalten, dass ich die Spalten aus Tabelle C optional abfrage wenn ein Link in Tabelle B vorhanden ist und ansonsten nur die Spalten aus A abfrage? Geht sowas überhaupt?

    Vielen Dank für eure Hilfe!



  • Du kannst zwei Abfragen mit UNION ALL verknüpfen. In der ersten der inner join über die drei Tabellen, in der zweiten ein Left join zwischen Tabelle a und Tabelle b wo in der WHERE-Bedingung die Primschlüsselspalte von B NULL ist. Dann entsprechend in der zweiten Abfrage die fehlenden Spalten mit NULL auffüllen.



  • Wieso sollte hier ein einfacher LEFT JOIN nicht reichen? Also A LEFT JOIN B INNER JOIN C halt.

    Verstehe nicht wozu man hier UNION ALL brauchen würde.



  • Wenn dann doch einen OUTER-Join, oder was übersehe ich hier?
    Mit 3 Tabellen unter einem MS-SQL-Server hatte ich aber auch so meine Schwierigkeiten und habs nur über eine UNION lösen können. Entweder fehlten mir sonst Einträge, respektive ich hatte doppelte Einträge...



  • Vielen Dank schonmal für eure Antworten. Wenn ich das richtig verstanden habe ist die Lösung von witte korrekt? Ich habe mal versucht das bei mir umzusetzen:

    SELECT TabA.Column1, TabA.Column2, TabA.Column3, TabC.Column1 
    FROM TabA 
    INNER JOIN TabB ON TabA.Column1 = TabB.Column1
    INNER JOIN TabC ON TabB.Column1 = TabC.Column1
    WHERE TabA.Column1 = @Param
    UNION ALL
    SELECT TabA.Column1, TabA.Column2, TabA.Column3
    FROM TabA
    LEFT JOIN TabA ON TabA.Column1 = TabB.Column1
    WHERE TabA.Column1 = NULL
    

    Dann kommt bei mir allerdings die Fehlermeldung von der Datenbank, dass das SQL-Statement nicht vollständig wäre. Wenn ich in meinen zweiten SELECT-Teil die Spalte aus Tabelle C wieder mit reinnehme, dann muss ich ja auch die Tabelle C wieder joinen, oder? Aber genau das will ich ja nicht, ich will dann ja nur die Spalten aus Tabelle A abfragen. Wo liegt da jetzt mein Denkfehler?



  • Wenn Du es mit einem UNION machen willst dann

    SELECT TabA.Column1, TabA.Column2, TabA.Column3, TabC.Column1
    FROM TabA
    INNER JOIN TabB ON TabA.Column1 = TabB.Column1
    INNER JOIN TabC ON TabB.Column1 = TabC.Column1
    WHERE TabA.Column1 = @Param
    UNION ALL
    SELECT TabA.Column1, TabA.Column2, TabA.Column3, NULL
    FROM TabA
    LEFT JOIN TabA ON TabA.Column1 = TabB.Column1
    WHERE TabB.Column1 = NULL
    

    Wenn Du einen Outer Join nehmen willst dann

    SELECT TabA.Column1, TabA.Column2, TabA.Column3, TabC.Column1
    FROM TabA
    LEFT JOIN TabB ON TabA.Column1 = TabB.Column1
    INNER JOIN TabC ON TabB.Column1 = TabC.Column1
    

    Der Outer join ist einfacher.
    BTW. Sind wirklich Tabellen A und C über die gleiche TabB.Column1 verknüpft?



  • Joe_M. schrieb:

    Wenn dann doch einen OUTER-Join, oder was übersehe ich hier?

    Ein LEFT JOIN *ist* ein OUTER JOIN...
    Wenn man will kann man auch LEFT OUTER JOIN schreiben.



  • Danke witte. Ich habe beide Methoden (UNION und LEFT JOIN) ausprobiert, bekomme aber nichts von der Datenbank zurück, obwohl ich weiss, dass der Datensatz den ich abfrage sicher Daten enthält. Woran kann das liegen? Ich habe den Code wie angegeben eingesetzt.

    SELECT TabA.Column1, TabA.Column2, TabA.Column3, TabC.Column1
    FROM TabA
    INNER JOIN TabB ON TabA.Column1 = TabB.Column1
    INNER JOIN TabC ON TabB.Column2 = TabC.Column1
    WHERE TabA.Column1 = @Param
    UNION ALL
    SELECT TabA.Column1, TabA.Column2, TabA.Column3, NULL
    FROM TabA
    LEFT JOIN TabB ON TabA.Column1 = TabB.Column1
    WHERE TabB.Column1 = NULL
    

    und

    SELECT TabA.Column1, TabA.Column2, TabA.Column3, TabC.Column1
    FROM TabA
    LEFT JOIN TabB ON TabA.Column1 = TabB.Column1
    INNER JOIN TabC ON TabB.Column2 = TabC.Column1 
    WHERE TabB.Column1 = NULL
    

    Ich bekomme zumindestens keinen Fehler von der Datenbank zurück, also ist das Statement grundsätzlich richtig. Aber irgendwas scheint dennoch noch falsch zu sein, da ich ja, obwohl in Tabelle A Daten vorhanden sind, trotzdem keine angezeigt bekomme 😞 .

    P.S.: Nein, Tabelle A und C sind nicht über die gleiche Spalte in B verknüpft, sorry, da habe ich mich vertippt.



  • Ahh, schon wieder vertippt. Im zweiten Teil mit dem LEFT OUTER JOIN ist die vierte Spalte (TabC.Column1) natürlich NULL.



  • Hm.
    Ich bin wohl auch schon etwas doof geworden auf meine alten Tage.
    Du musst 2x LEFT JOIN nehmen. Sorry.
    Wenn der 1. LEFT JOIN nämlich nix findet, dann steht da ne NULL. Und der INNER JOIN will dann ne NULL joinen. Was nicht funktioniert. (Zumindest nicht wenn es keinen Key mit dem Wert NULL gibt, was ja hoffentlich so sein wird)



  • Danke hustbaer, so funktionierts!!


Anmelden zum Antworten