Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi SQL | INNER JOINS über mehrere Tabellen (https://www.delphipraxis.net/135342-sql-%7C-inner-joins-ueber-mehrere-tabellen.html)

f4k3 9. Jun 2009 10:43

Datenbank: Firebird • Version: 2.1 • Zugriff über: ZEOS

SQL | INNER JOINS über mehrere Tabellen
 
Moin Moin liebe DPler ;)

hab mal ne Frage ... und zwar hab ich ne Abfrage gemacht die mir sämlichste Informationen über
einen "Kontakt" holt.

Ich bekommen einen Dynamic SQL Error SQL error code = -204

Also hab ich mir auf der Firebird Seite die Firebird 2.1 Error Codes angekuckt ... nur kommen da leider mehrere Ursachen in Frage ... und ich komm einfach nicht drauf...

Vielleicht sieht jemand mit seinem geschulten Auge den Fehler ...

Das ist mein Code ...
SQL-Code:
SELECT
    k.KON_ID, k.KONTAKTART_ID, k.VORNAME as firstname, k.NACHNAME as lastname,
    k.FIRMA as company, k.ANGELEGT, k.GEAENDERT,
   
    kk.KON_KONTAKTART_ID, kk.BEZEICHNUNG, kk.BESCHREIBUNG,
   
    kt.KON_TELEFON_ID, kt.KONTAKT_ID, kt.KONTAKTART_ID, kt.ANSPRECHPARTNER as contact,
    kt.RUFNUMMER as phone,
   
    kabt.KON_ABTEILUNG_ID, kabt.ABTEILUNG,
   
    kasp.KON_ANSPRECHPARTNER_ID, kasp.KONTAKT_ID, kasp.ABTEILUNG_ID,
    kasp.VORNAME, kasp.NACHNAME

FROM KON_TELEFON kt

  INNER JOIN KON k
    ON (kt.KONTAKT_ID = k.KON_ID)
  INNER JOIN KON_KONTAKTART kk
    ON (k.KONTAKTART_ID = kk.KON_KONTAKTART_ID)
  INNER JOIN KON_KONTAKTART kk
    ON (kt.KONTAKTART_ID = kk.KON_KONTAKTART_ID)
  INNER JOIN KON_ABTEILUNG kabt
    ON ((kasp.ABTEILUNG_ID = kabt.KON_ABTEILUNG_ID))
  INNER JOIN KON_ANSPRECHPARTNER kasp
    ON (kasp.KONTAKT_ID = k.KON_ID)              
 
WHERE kt.RUFNUMMER = '123'
Das natürlich nur ein Testcode ;)

Vielen dank für eure Posts

Euer f4k3 :stupid:

[b]//edit: Beim Öffnen des Links kann es passieren, da das Dokument im PDF-Format vorliegt, dass es ziemlich lange
dauert bis es geöffnet ist ... Größe des Dokuments ~ 104 Kb ... nur so als kleine Info am Rande ;)

Leonard 9. Jun 2009 11:13

Re: SQL | INNER JOINS über mehrere Tabellen
 
Hallo,

Zitat:

Zitat von f4k3
SQL-Code:
  INNER JOIN KON_KONTAKTART kk
    ON (k.KONTAKTART_ID = kk.KON_KONTAKTART_ID)
  INNER JOIN KON_KONTAKTART kk
    ON (kt.KONTAKTART_ID = kk.KON_KONTAKTART_ID)

ich würde sagen in deinem Fall ist es ein alias_conflict_err, da du den Tabellenalias kk 2-mal verwendest.

f4k3 9. Jun 2009 11:14

Re: SQL | INNER JOINS über mehrere Tabellen
 
Zitat:

Zitat von Leonard
Hallo,

Zitat:

Zitat von f4k3
SQL-Code:
  INNER JOIN KON_KONTAKTART kk
    ON (k.KONTAKTART_ID = kk.KON_KONTAKTART_ID)
  INNER JOIN KON_KONTAKTART kk
    ON (kt.KONTAKTART_ID = kk.KON_KONTAKTART_ID)

ich würde sagen in deinem Fall ist es ein alias_conflict_err, da du den Tabellenalias kk 2-mal verwendest.

mhm ... dat is schlecht ... weil ich beide Prüfungen brauche ...
aber JOINS lassen sich bestimmt mit AND, OR, XOR verknüpfen oder?

Dann könnte ich es ja so lösen ...

Leonard 9. Jun 2009 11:28

Re: SQL | INNER JOINS über mehrere Tabellen
 
Zitat:

Zitat von f4k3
mhm ... dat is schlecht ... weil ich beide Prüfungen brauche ...
aber JOINS lassen sich bestimmt mit AND, OR, XOR verknüpfen oder?

Das sollte gehen. Kann es aber auch sein, dass in k.KON_KONTAKTART_ID und kt.KON_KONTAKTART_ID die gleichen Werte stehen?

Noch etwas anderes ist mir jetzt aufgefallen. Es kann auch noch sein, dass du die letzten beiden INNER JOIN Anweisungen tauschen musst. Die Verknüpfung zu kasp wird erst in der letzten Anweisung erstellt, aber schon in der vorherigen verwendet. Es kann aber sein, dass Firebird das so kann.

Alt:
SQL-Code:
INNER JOIN KON_ABTEILUNG kabt ON (kasp.ABTEILUNG_ID = kabt.KON_ABTEILUNG_ID)
INNER JOIN KON_ANSPRECHPARTNER kasp ON (kasp.KONTAKT_ID = k.KON_ID)

Neu:
SQL-Code:
INNER JOIN KON_ANSPRECHPARTNER kasp ON (kasp.KONTAKT_ID = k.KON_ID)
INNER JOIN KON_ABTEILUNG kabt ON (kasp.ABTEILUNG_ID = kabt.KON_ABTEILUNG_ID)

f4k3 9. Jun 2009 11:44

Re: SQL | INNER JOINS über mehrere Tabellen
 
Zitat:

Zitat von Leonard
Zitat:

Zitat von f4k3
mhm ... dat is schlecht ... weil ich beide Prüfungen brauche ...
aber JOINS lassen sich bestimmt mit AND, OR, XOR verknüpfen oder?

Das sollte gehen. Kann es aber auch sein, dass in k.KON_KONTAKTART_ID und kt.KON_KONTAKTART_ID die gleichen Werte stehen?

Noch etwas anderes ist mir jetzt aufgefallen. Es kann auch noch sein, dass du die letzten beiden INNER JOIN Anweisungen tauschen musst. Die Verknüpfung zu kasp wird erst in der letzten Anweisung erstellt, aber schon in der vorherigen verwendet. Es kann aber sein, dass Firebird das so kann.

Alt:
SQL-Code:
INNER JOIN KON_ABTEILUNG kabt ON (kasp.ABTEILUNG_ID = kabt.KON_ABTEILUNG_ID)
INNER JOIN KON_ANSPRECHPARTNER kasp ON (kasp.KONTAKT_ID = k.KON_ID)

Neu:
SQL-Code:
INNER JOIN KON_ANSPRECHPARTNER kasp ON (kasp.KONTAKT_ID = k.KON_ID)
INNER JOIN KON_ABTEILUNG kabt ON (kasp.ABTEILUNG_ID = kabt.KON_ABTEILUNG_ID)

Alles klar ;) ... Die alte Variante funktioniert aber auch ... habs in Database Workbench 3 Lite for Firebird getestet.

Mir is nur n kleiner Fehler unterlaufen ... also ich möchte ja nur die Informationen zu einem bestimmten Kontakt.
und ich hab 8 Tabellen für meine Kontaktverwaltung (kommen später noch mehr) ... Es ist aber keine notwendigkeit dass
in allen Tabellen Informationen zum Kontakt vorhanden sein müssen. Wenn bei meiner Abfrage jedoch in einem JOIN kein
Datensatz gefunden wird ... ist der Kontakt auch nicht in der Ergebnismenge obwohl ich genau nach diesem Kontakt Suche ...

Muss ich dass dann mit einem OUTER JOIN lösen oder alle JOINS rausschmeissen und die Daten händisch abfragen? mit einer WHERE-Klausel?

Ich hab nämlich mein Lösungsansatz mal an ein paar Testdaten ausprobiert und bin drauf gestossen dass ich nach einem
Benutzer suche ... der aber nicht in der Ergebnismenge auftaucht obwohl er vorhanden ist, weil eben in 2 Tabellen die mit
JOINS abgefragt werden keine Werte zu diesem Nutzer enthalten sind ... wenn ich Werte einfüge wird der Benutzer angezeigt ... :(

Hier mal die Abfrage ...

SQL-Code:
SELECT

    // BEN
    b.BEN_ID, b.RECHTE_ID, b.ABTEILUNG_ID, b.BENUTZERNAME, b.PASSWORT,
    b.VORNAME, b.NACHNAME, b.GEBURTSTAG, b.EINSTELLUNGSDATUM, b.ENTLASSUNGSDATUM,
    b.EINGELOGGT,
   
    // BEN_ABTEILUNG
    bab.BEN_ABTEILUNG_ID, bab.ABTEILUNGSNAME,
   
    // BEN_ADRESSE
    bad.BEN_ADRESSE_ID, bad.BENUTZER_ID, bad.KONTAKTART_ID, bad.STRASSE,
    bad.POSTLEITZAHL, bad.ORT,
   
    // BEN_EMAIL
    be.BEN_EMAIL_ID, be.BENUTZER_ID, be.KONTAKTART_ID, be.EMAIL_ADRESSE,
   
    // BEN_KONTAKTART
    bk.BEN_KONTAKTART_ID, bk.BEZEICHNUNG, bk.BESCHREIBUNG,
   
    // BEN_NOTIZEN
    bn.BEN_NOTIZEN_ID, bn.BENUTZER_ID, bn.BEZEICHNUNG, bn.BESCHREIBUNG,
    bn.ANGELEGT, bn.GEAENDERT,
   
    // BEN_RECHTE
    br.BEN_RECHTE_ID, br.BEZEICHNUNG, br.ADMINISTRATOR,
   
    // BEN_TELEFON
    bt.BEN_TELEFON_ID, bt.BENUTZER_ID, bt.KONTAKTART_ID, bt.RUFNUMMER

FROM BEN b, BEN_KONTAKTART bk

    // INNER JOIN BEN_RECHTE
    INNER JOIN BEN_RECHTE br
      ON (b.RECHTE_ID = br.BEN_RECHTE_ID)
   
    // INNER JOIN BEN_ABTEILUNG
    INNER JOIN BEN_ABTEILUNG bab
      ON (b.ABTEILUNG_ID = bab.BEN_ABTEILUNG_ID)
   
    // INNER JOIN BEN_ADRESSE
    INNER JOIN BEN_ADRESSE bad
      ON (bad.BENUTZER_ID = b.BEN_ID)
   
    // INNER JOIN BEN_EMAIL
    INNER JOIN BEN_EMAIL be
      ON (be.BENUTZER_ID = b.BEN_ID)
   
    // INNER JOIN BEN_NOTIZEN
    INNER JOIN BEN_NOTIZEN bn
      ON (bn.BENUTZER_ID = b.BEN_ID)
   
    // INNER JOIN BEN_TELEFON
    INNER JOIN BEN_TELEFON bt
      ON (bt.BENUTZER_ID = b.BEN_ID) AND (bt.KONTAKTART_ID = bk.BEN_KONTAKTART_ID)

WHERE b.BENUTZERNAME = 'Jonny'
MfG f4k3

f4k3 9. Jun 2009 11:48

Re: SQL | INNER JOINS über mehrere Tabellen
 
Also hab grad gelesen dass ich es mit einem LEFT OUTER JOIN machen könnte.

Ich probier dass ganze mal aus ;)

f4k3 9. Jun 2009 11:59

Re: SQL | INNER JOINS über mehrere Tabellen
 
Also ich habs probiert ;)

SQL-Abfrage ...

SQL-Code:
SELECT

    // BEN
    b.BEN_ID, b.RECHTE_ID, b.ABTEILUNG_ID, b.BENUTZERNAME, b.PASSWORT,
    b.VORNAME, b.NACHNAME, b.GEBURTSTAG, b.EINSTELLUNGSDATUM, b.ENTLASSUNGSDATUM,
    b.EINGELOGGT,
   
    // BEN_ABTEILUNG
    bab.BEN_ABTEILUNG_ID, bab.ABTEILUNGSNAME,
   
    // BEN_ADRESSE
    bad.BEN_ADRESSE_ID, bad.BENUTZER_ID, bad.KONTAKTART_ID, bad.STRASSE,
    bad.POSTLEITZAHL, bad.ORT,
   
    // BEN_EMAIL
    be.BEN_EMAIL_ID, be.BENUTZER_ID, be.KONTAKTART_ID, be.EMAIL_ADRESSE,
   
    // BEN_KONTAKTART
    bk.BEN_KONTAKTART_ID, bk.BEZEICHNUNG, bk.BESCHREIBUNG,
   
    // BEN_NOTIZEN
    bn.BEN_NOTIZEN_ID, bn.BENUTZER_ID, bn.BEZEICHNUNG, bn.BESCHREIBUNG,
    bn.ANGELEGT, bn.GEAENDERT,
   
    // BEN_RECHTE
    br.BEN_RECHTE_ID, br.BEZEICHNUNG, br.ADMINISTRATOR,
   
    // BEN_TELEFON
    bt.BEN_TELEFON_ID, bt.BENUTZER_ID, bt.KONTAKTART_ID, bt.RUFNUMMER

FROM BEN b, BEN_KONTAKTART bk

    // INNER JOIN BEN_RECHTE
    LEFT OUTER JOIN BEN_RECHTE br
      ON (br.BEN_RECHTE_ID = b.RECHTE_ID)
   
    // INNER JOIN BEN_ABTEILUNG
    LEFT OUTER JOIN BEN_ABTEILUNG bab
      ON (bab.BEN_ABTEILUNG_ID = b.ABTEILUNG_ID)
   
    // INNER JOIN BEN_ADRESSE
    LEFT OUTER JOIN BEN_ADRESSE bad
      ON (bad.BENUTZER_ID = b.BEN_ID)
   
    // INNER JOIN BEN_EMAIL
    LEFT OUTER JOIN BEN_EMAIL be
      ON (be.BENUTZER_ID = b.BEN_ID)
   
    // INNER JOIN BEN_NOTIZEN
    LEFT OUTER JOIN BEN_NOTIZEN bn
      ON (bn.BENUTZER_ID = b.BEN_ID)
   
    // INNER JOIN BEN_TELEFON
    LEFT OUTER JOIN BEN_TELEFON bt
      ON (bt.BENUTZER_ID = b.BEN_ID) AND (bt.KONTAKTART_ID = bk.BEN_KONTAKTART_ID)

WHERE b.BENUTZERNAME = 'Jonny'
Als Ergebnis bekomme ich zwar keinen Fehler ... aber eine Informatione "no current record for fetch operation" was soviel heißt wie kein Datensatz für fetch-operation verfügbar, wenn mich mein Englisch nicht im stich lässt :P

Bis auf BEN_NOTIZEN enthalten aber alle Tabellen Informationen die mit dem Benutzer verknüpft sind ...
Und so wie ich den LEFT OUTER JOIN verstanden habe ... müssten alle Daten geliefert werden zu denen eine Verknüpfung existiert :gruebel:

Oder hab ich das Prinzip nicht ganz verstanden?

MfG f4k3

DeddyH 9. Jun 2009 12:08

Re: SQL | INNER JOINS über mehrere Tabellen
 
Bekommst Du ein Ergebnis, wenn Du die ganzen Joins und damit verbundenen Tabellen/Felder weglässt? Vielleicht war es nur ein Tippfehler und es existiert gar kein solcher Benutzer in der Haupttabelle.

f4k3 9. Jun 2009 12:15

Re: SQL | INNER JOINS über mehrere Tabellen
 
Zitat:

Zitat von DeddyH
Bekommst Du ein Ergebnis, wenn Du die ganzen Joins und damit verbundenen Tabellen/Felder weglässt? Vielleicht war es nur ein Tippfehler und es existiert gar kein solcher Benutzer in der Haupttabelle.

Also wenn ich nur die Haupttabelle abfrage "BEN" dann bekomme ich die Informationen ... aber eben nur aus dieser einen
Tabelle ...

Aber ich glaub ich muss meine Normalisierung mal überdenken ... ich habs zwar noch nicht ausgiebig geprüft ... aber ich glaube
es gibt ein paar Unstimmigkeiten ...

Ein Benutzer kann zum Beispiel in BEN_EMAIL mehrere E-Mail-Adressen haben die wiederum unterteilt werden in eine KONTAKTART wie z.B: intern, privat. Die Tabelle BEN_EMAIL trägt also noch ein Feld "KONTAKTART_ID" dass auf die TABELLE BEN_KONTAKTART->BEN_KONTAKTART_ID verweist ...

vielleicht liegt darin der Fehler dass die einzelnen Tabellen teilweise auch noch mit anderen Tabellen verknüpft sind ...

DeddyH 9. Jun 2009 12:38

Re: SQL | INNER JOINS über mehrere Tabellen
 
Dann hätte die Abfrage aber ein Ergebnis liefern müssen, wenn ich das richtig überschaut habe. Gibt es in den Detailtabellen keinen passenden Datensatz, enthalten die Felder bei einem OUTER JOIN dann NULL-Werte.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:09 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz