Datenbank Abfrage



  • Hallo,

    meine Datenbankstruktur:

    Tabelle Autor: Autor_ID, Name, Vorname............PK: Autor_ID
    Tabelle Buch: Buch_ID, Name, Vorlag.................PK: Buch_ID
    Tabelle Autor2Buch: Autor_ID, Buch_ID.............Verknüpfungstabelle

    Wie lauten folgende Abfragen:

    1. Wie heisst Autor/en der Buch mit Buch_ID=2 geschrieben hat.
    2. Wie heisst Autor/en der Buch mit Namen "Harry Potter" geschrieben hat



  • zu 1) Select name,vorname from Autor where Autor_ID in (Select Autor_ID from Autor2Buch where Buch_ID = 2)



  • Sub-Select auf die Verknüpfungstabelle? Warum? Schau Dir noch mal den Aufbau der Tabelle Autor an...



  • Million Voices schrieb:

    Sub-Select auf die Verknüpfungstabelle? Warum? Schau Dir noch mal den Aufbau der Tabelle Autor an...

    ...ja?
    Vielleicht solltest du besser nochmal gucken?



  • hustbaer schrieb:

    Vielleicht solltest du besser nochmal gucken?

    Ähm ja, hust... Ich nehm's zurück.



  • Also zu 1) hab ich jetzt schon mal eine Lösung. Hab die Namen nun zwar auf englisch aber es kommt das richtige raus. Nur komischerweise gibt er den Author doppelt zurück . Hmm...

    Select firstname,lastname from author inner JOIN author2book on author.authorID in(SELECT author2book.authorId from author2book where bookID = 2)



  • Wie kommst du denn auf das Konstrukt INNER JOIN ... ON xxx IN () 😕 Das habe ich in 15 Jahren SQL noch nie gesehen. Ist schon klar dass es möglich ist, aber macht für mich überhaupt keinen Sinn.

    Egal, der Grund dass du es doppelt bekommst ist dass du von where Autor_ID in zu INNER JOIN umgestiegen bist.
    So funktioniert ein Join halt - wenn der Author (linke Join Seite) 2 Bücher geschrieben hat (rechte Join Seite), dann bekommst du 2 Zeilen im Ergebnis. Wobei die linke Seite dann halt dupliziert wird.

    Ich würde hier einfach mit WHERE xxx IN oder auch mit WHERE EXISTS arbeiten.



  • Lösung zu 2)

    Select firstname,lastname from author inner JOIN author2book where author.authorID in (Select author2book.AuthorID from author2book where author2book.BookID = (Select book.BookID from book where book.Title = 'Potter') )

    Und bei inner join verwendet man statt where wohl on so hab ich's gelernt und so steht es auch bei w3schools



  • hustbaer schrieb:

    So funktioniert ein Join halt - wenn der Author (linke Join Seite) 2 Bücher geschrieben hat

    Ich hab da aber nur 1 Buch drin. Trotzdem bekomm ich 2 mal das gleiche. Kann doch nicht sein.... Die können doch nicht verlangen dass ich Select Distinct mache. Da ist dann die Anfrage noch irgendwo nicht ganz richtig....



  • Oioioioi...

    Also ein JOIN versucht jede Zeile des linken Teils mit jeder Zeile des rechten Teils zu kombinieren.
    Dabei entstehen N * M potentielle Zeilen (mit N = Anzahl Zeilen im linken Teil und M = Anzahl Zeilen im rechten Teil).
    Im "ON" Teil gibt man dabei an welche Bedingung erfüllt sein muss damit die Kombination der beiden Teile "erwünscht" ist, also "erzeugt" werden soll.

    Die verschiedenen JOIN Typen:

    CROSS JOIN: Es gibt keinen "ON" Teil, es werden alle Kombinationen erzeugt. Eben das "Kreuzprodukt" der beiden Tabellen (Teile).

    INNER JOIN: Es werden nur Kombinationen erzeugt für die der "ON" Teil erfüllt ist.

    LEFT OUTER JOIN: Es werden alle Kombinationen erzeugt für die der "ON" Teil erfüllt ist. Zusätzlich werden alle Zeilen des linken Teils zurückgegeben für die der "ON" Teil bei keiner Kombination erfüllt war. Dabei (=bei diesen zusätzlichen Zeilen) werden alle Spalten im Ergebnis die vom rechten Teil stammen würden als NULL zurückgegeben.

    RIGHT OUTER JOIN: Es werden alle Kombinationen erzeugt für die der "ON" Teil erfüllt ist. Zusätzlich werden alle Zeilen des rechten Teils zurückgegeben für die der "ON" Teil bei keiner Kombination erfüllt war. Dabei werden alle Spalten im Ergebnis die vom linken Teil stammen würden als NULL zurückgegeben.

    FULL OUTER JOIN: Es werden alle Kombinationen erzeugt für die der "ON" Teil erfüllt ist. Zusätzlich werden alle Zeilen des linken und rechten Teils zurückgegeben für die der "ON" Teil bei keiner Kombination erfüllt war. Dabei werden alle Spalten im Ergebnis die vom jeweils nicht beteiligten Teil stammen als NULL zurückgegeben.

    Wenn wir uns jetzt deine Query ansehen...

    SELECT
        firstname, lastname
    FROM
        author
        INNER JOIN author2book
            ON author.authorID IN (SELECT author2book.authorId FROM author2book WHERE bookID = 2)
    

    Es werden also alle Kombinationen aus Zeilen in author "cross" Zeilen in author2book probiert.
    Die wo die Bedingung author.authorID IN (SELECT author2book.authorId FROM author2book WHERE bookID = 2) zutrifft werden zurückgegeben.

    Diese Bedingung ist nun aber überhaupt nicht vom rechten JOIN Teil abhängig.
    Du machst ja im "IN" Teil ein SELECT auf author2book , die author2book -Felder die du darin referenzierst beziehen sich also NICHT auf den rechten JOIN-Teil sondern auf das SELECT innerhalb der Klammern!
    D.h. angenommen die Query SELECT author2book.authorId FROM author2book WHERE bookID = 2 würde als Ergebnis 1 und 2 zurückgeben, dann wäre deine "ON" Bedingung:
    author.authorID IN (1, 2)

    Und nu nochmal: Es werden alle N * M Konbinationen aus author und author2book Zeilen probiert, wobei du in der "ist die Kombination erwünscht"-Bedingung den Inhalt der author2book Zeile komplett ignorierst. D.h. du bekommst im Ergebnis zeilen der Autoren 1 und 2, und zwar so oft dupliziert wie es Zeilen in author2book gibt!

    (Und deswegen bekommst du im Ergebnis Duplikate. Derzeit bekommst du alles "nur" doppelt, weil du in author2book bloss zwei Zeilen hast. Würdest du mehr author2book Zeilen einfügen (egal mit welchen IDs!), würdest du alles 3x, 4x - beliebig oft bekommen.)

    Also schreib es ohne JOIN, oder so wie normale Programmierer einen JOIN schreiben.



  • hustbaer schrieb:

    Wie kommst du denn auf das Konstrukt INNER JOIN ... ON xxx IN ()

    Ich würde hier einfach mit WHERE xxx IN oder auch mit WHERE EXISTS arbeiten.

    wenn ich

    select firstname, lastname from author, author2book where author.author.id = (Select author2book.authorid from author2book where bookId = 1 )

    mache, bekomm ich immer noch die Duplikate. Jetzt benutz ich kein join mehr...



  • select firstname, lastname from author where author.author.id = (Select author2book.authorid from author2book where bookId = 1 )
    

    Jetzt immer noch? Wenn ja, würde ich gerne den Inhalt der Tabellen sehen.



  • Jetzt nicht mehr. Der inner join war also nie nötig 🙂



  • Peter_Mueller schrieb:

    wenn ich

    select firstname, lastname from author, author2book where author.author.id = (Select author2book.authorid from author2book where bookId = 1 )

    mache, bekomm ich immer noch die Duplikate. Jetzt benutz ich kein join mehr...

    Doch, klar verwendest du immer noch nen JOIN.

    FROM author, author2book

    ist bloss 'ne alternative Schreibweise für

    FROM author CROSS JOIN author2book

    Und nein, natürlich war der JOIN nie nötig. Wurde auch nie behauptet 🙂


Log in to reply