Yadgar: Problem mit JOIN

High!

Folgendes Problem: Zwei Tabellen: instrumentenhersteller (mit den Spalten ID und Name), instrumentenmodelle (mit den Spalten ID, Hersteller, Modell, Typ).

Da die Spalte "Typ" in "instrumentenmodelle" sich auf die Spalte "instrumente" bezieht, es in den konkreten Rohdaten aber durchaus vorkommen kann, dass nur das Instrument (z. B. elektronische Orgel, Synthesizer etc.) bekannt ist, nicht aber Hersteller und Modellbezeichnung, stehen in "instrumentenmodelle" unter "Modell" auch die Bezeichnungen aus "instrument", "Hersteller" hat dann logischerweise den Wert 0.

Wenn ich jetzt versuche, Modell und Hersteller (sofern vorhanden) in einer Tabelle anzeigen zu lassen:

  
SELECT instrumentenhersteller.Name, instrumentenmodelle.Modell FROM instrumentenmodelle LEFT JOIN instrumentenhersteller ON instrumentenmodelle.Hersteller = instrumentenhersteller.ID OR instrumentenmodelle.Hersteller = 0 ORDER BY Hersteller, Modell  

bekomme ich für die Tupel, wo "Hersteller" 0 ist, eine Kreuzverknüpfung angezeigt, die übrigen Tupel jedoch nur einmal. Das sieht so aus:

Name             Modell
Korg             elektronische Orgel
Yamaha           elektronische Orgel
Hammond          elektronische Orgel
Yamaha           elektronische Orgel
Korg             elektronische Orgel
Hammond          elektronische Orgel
Yamaha           Electone C-55N
Yamaha           SY-55
Hammond          B3

Richtig wäre es so:

Name             Modell
                 elektronische Orgel
                 elektronische Orgel
Yamaha           Electone C-55N
Yamaha           SY-55
Hammond          B3

Wie bekomme ich das hin?

Bis bald im Khyberspace!

Yadgar

  1. Moin!

    Da die Spalte "Typ" in "instrumentenmodelle" sich auf die Spalte "instrumente" bezieht, es in den konkreten Rohdaten aber durchaus vorkommen kann, dass nur das Instrument (z. B. elektronische Orgel, Synthesizer etc.) bekannt ist, nicht aber Hersteller und Modellbezeichnung, stehen in "instrumentenmodelle" unter "Modell" auch die Bezeichnungen aus "instrument", "Hersteller" hat dann logischerweise den Wert 0.

    Logisch wäre, den Wert NULL einzutragen, nicht 0.

    SELECT instrumentenhersteller.Name, instrumentenmodelle.Modell FROM instrumentenmodelle LEFT JOIN instrumentenhersteller ON instrumentenmodelle.Hersteller = instrumentenhersteller.ID OR instrumentenmodelle.Hersteller = 0 ORDER BY Hersteller, Modell

    
    >   
    > bekomme ich für die Tupel, wo "Hersteller" 0 ist, eine Kreuzverknüpfung angezeigt, die übrigen Tupel jedoch nur einmal.  
      
    Das liegt an deiner Join-Bedingung. Du joinst mit allen Werten der linken Tabelle, wenn rechts eine 0 eingetragen ist.  
      
    Eigentlich willst du für "nicht bekannter Wert" NULL in die Tabelle eintragen und deine Abfrage als OUTER JOIN gestalten, wobei LEFT oder RIGHT OUTER JOIN passen könnte, jenachdem, ob deine NULL-Werte-Tabelle links oder rechts im Join steht.  
      
    Ein OUTER JOIN nimmt alle Tabelleneinträge der ersten (links oder rechts stehenden) Tabelle und verknüpft dann, wenn ein Eintrag in der zweiten Tabelle gefunden wurde, diesen. Bei NULL wird kein Wert gefunden, die Spalten der zweiten Tabelle daher mit NULL als Lückenfüllern aufgefüllt und zurückgegeben.  
      
    Dein User-Interface muss noch entsprechend angepasst werden dahingehend, dass man "kenn ich nicht/unbekannt" auswählen kann, und in die DB dann NULL als Wert eingetragen wird. Wenn du bislang die 0 als Wert für diesen Fall genommen hast, die Wahlmöglichkeit aber schon existiert, sollte sich die Anpassung auf das Wandeln der 0 in NULL an geeigneter Stelle beschränken. Die Ausgabe von NULL-Werten erfordert dann evtl. auch noch etwas optisches Anpassen.  
      
     - Sven Rautenberg
    
    1. High!

      Logisch wäre, den Wert NULL einzutragen, nicht 0.

      Ich habe die Abfrage mit PHPMyAdmin getestet - und da wird bei Schlüsselverweisen auf nicht vorhandene Spalteneinträge nicht zwischen NULL und 0 unterschieden, in den angezeigten Ergebnistabellen steht dann einfach 0...

      Mit LEFT OUTER JOIN und Prüfung auf NULL hat es aber funktioniert - danke für den Hinweis!

      Bis bald im Khyberspace!

      Yadgar