AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Baumansicht

Ein Thema von theomega · begonnen am 4. Aug 2003 · letzter Beitrag vom 7. Aug 2003
Antwort Antwort
Benutzerbild von theomega
theomega

Registriert seit: 18. Jun 2002
684 Beiträge
 
#1

Baumansicht

  Alt 4. Aug 2003, 15:57
Hallo Leute
jetzt wirds ein bischen komplex, gesucht wird ein SQL-Statement oder ein Code.

Ich habe 4 Tabellen:

1. sachbuch:
- sbid (PRIMARY_KEY)
- sbnr (VAR_CHAR)

2. gliederung:
- glid (PRIMARY_KEY)
- glnr (VAR_CHAR)
- sbnr (VAR_CHAR)

3. funktion:
- fnid (PRIMARY_KEY)
- fnnr (VAR_CHAR)
- glnr (VAR_CHAR)

4. konto
- knid (PRIMARY_KEY)
- knnr (VAR_CHAR)
- fnnr (VAR_CHAR)

So:
Immer gleichnamige Felder sind verknüpft. Es ist aber nicht eine 1:1 verknüpfung sondern 1:n es können also in einem Sachbuch mehrere Gliederungen vorhanden sein und auch in den anderen Tabellen.

Bis jetzt habe ich das extrem umständlich gelößt, und habe für einen kleinen Baum knapp 160 Query gebraucht. Das ist viel zu viel, das sollte doch auch mit einem und einem INNER oder OUTER Join funktionieren. Nur irgendwie steig ich nicht so komplett durch.

Datenbank-Anwendung ist Firebird über die Interbase-Kompos. Delphi ist 7.

Nacher sollen die Daten in einem Treeview angezeigt werden.

Vielen Dank

TheOmega.
  Mit Zitat antworten Zitat
Benutzerbild von theomega
theomega

Registriert seit: 18. Jun 2002
684 Beiträge
 
#2

Re: Baumansicht

  Alt 5. Aug 2003, 20:12
Keiner auch nur eine Idee? Evtl einen Befehl, der mir helfen könnte?
  Mit Zitat antworten Zitat
Florian_S

Registriert seit: 5. Aug 2003
16 Beiträge
 
Delphi 7 Professional
 
#3

Re: Baumansicht

  Alt 5. Aug 2003, 20:33
hat sich ja jetzt erledigt.
  Mit Zitat antworten Zitat
frankg

Registriert seit: 20. Mai 2003
Ort: Wetter
72 Beiträge
 
Delphi 7 Architect
 
#4

Re: Baumansicht

  Alt 6. Aug 2003, 07:53
Hallo TheOmega!

Zitat von theomega:
Hallo Leute
jetzt wirds ein bischen komplex, gesucht wird ein SQL-Statement oder ein Code.
Naja, so komplex wirds auch wieder nicht

Zitat von theomega:
Ich habe 4 Tabellen:

1. sachbuch:
- sbid (PRIMARY_KEY)
- sbnr (VAR_CHAR)

2. gliederung:
- glid (PRIMARY_KEY)
- glnr (VAR_CHAR)
- sbnr (VAR_CHAR)

3. funktion:
- fnid (PRIMARY_KEY)
- fnnr (VAR_CHAR)
- glnr (VAR_CHAR)

4. konto
- knid (PRIMARY_KEY)
- knnr (VAR_CHAR)
- fnnr (VAR_CHAR)
Ich hab das hier mal aufgezeichnet...



Was mir an Deinem Datenbankdesign aufgefallen ist, ist dass Du zwar Primärschlüssel verwendest (z.B. sbid), dann aber von der anderen Tabelle aus einen Fremdschlüssel auf das Feld sbnr verwendest. Das hat zwei grosse Nachteile:
  • 1. Das Datenbanksystem kann nicht überprüfen, ob der in sbnr eingefügte Wert eindeutig ist (naja, kannst Du schon über UNIQUE machen, ist aber meiner Meinung nach hier unnötig). Sobald Du z.B. zwei Sachbücher mit derselben Information im Feld sbnr hast, hat Dein Datenbankmodell verloren.

    2. Wenn Du dafür sorgst, dass der Wert im Feld sbnr UNIQUE ist, dann hast Du redundante Informationen, weil Du in einem Datensatz ja zwei mal einen eindeutige Wert stehen hast.
Fremdschlüssel sollten in einem stimmigen, robuten Datenbank-Design immer auf Primärschlüssel einer Tabelle bezogen sein.

Ich würde das Problem folgendermassen lösen:



Nun sind alle Fremdschlüssel mit Primärschlüsseln verknüpft. Wenn Du nun noch mit Foreign Key Constraints arbeitest (ein Foreign Key Constraint definiert die Beziehung zwischen den Tabellen als Regel in der Datenbank, d.h. Du kannst in ein Foreign Key Feld keinen Wert mehr eintragen, der nicht bereits als Primary Key in der anderen Tabelle verwendet wird), dann hast Du ein absolut bombensicheres Datenbankmodell, weil es dann nicht mehr möglich ist Datensätze anzugeben, die nicht richtig verknüpft sind.

Zitat von theomega:
So:
Immer gleichnamige Felder sind verknüpft. Es ist aber nicht eine 1:1 verknüpfung sondern 1:n es können also in einem Sachbuch mehrere Gliederungen vorhanden sein und auch in den anderen Tabellen.

Bis jetzt habe ich das extrem umständlich gelößt, und habe für einen kleinen Baum knapp 160 Query gebraucht. Das ist viel zu viel, das sollte doch auch mit einem und einem INNER oder OUTER Join funktionieren. Nur irgendwie steig ich nicht so komplett durch.
160 Querys sind wirklich ein bisschen viel. Ich würde es mit der folgenden Query versuchen (Inner Join).

SQL-Code:
SELECT
  *
FROM
  SACHBUCH SB,
  GLIEDERUNG GL,
  FUNKTION FK,
  KONTO KO
WHERE
  (SB.SACHBUCH_ID = GL.SACHBUCH_ID) AND
  (GL.GLIEDERUNG_ID = FK.GLIEDERUNG_ID) AND
  (FK.FUNKTION_ID = KO.FUNKTION_ID);
Das ist zwar Oracle SQL, müsste unter Firebird aber auch funktionieren. Der angegebene SQL Befehl funktioniert aber nur für Datensätze, die auch über einen Fremdschlüssel verfügen, gibt es einen Datensatz, der keinen Wert im Feld Fremdschlüssel hat, so wird dieser aufgrund des verwendeten Inner-Joins (Ist sogar ein Equi-Join, weil die PK und FK Felder gleich heissen) nicht angezeigt. In diesem Fall musst Du einen Outer-Join verwenden. Wenn ich die Problemstellung allerdings richtig verstanden habe kann dieser Fall nicht vorkommen. Ich würde an Deiner Stelle diese Query dann als View in der Datenbank abspeichern. So kannst Du dann recht bequem über
SELECT * FROM myView; Auf die grosse Tabelle zugreifen. Natürlich kannst Du den View dann auch mit ner WHERE Klausel filtern.

Zitat von theomega:
Datenbank-Anwendung ist Firebird über die Interbase-Kompos. Delphi ist 7.

Nacher sollen die Daten in einem Treeview angezeigt werden.
Wie gesagt, meine Domäne ist Oracle und MS SQL, aber ich denke das sollte auch unter Firebird funktionieren.

Zitat von theomega:
Vielen Dank
Keine Ursache

Viele Grüsse

Frank
Miniaturansicht angehängter Grafiken
db2.gif   db1.gif  
  Mit Zitat antworten Zitat
Benutzerbild von theomega
theomega

Registriert seit: 18. Jun 2002
684 Beiträge
 
#5

Re: Baumansicht

  Alt 6. Aug 2003, 09:58
Jauh, das mit dem Unique ist mir auch schon aufgefallen, das werde ich sofort ändern (müßen). Aber wie machst du diese tollen verhältnis-Diagramme?
  Mit Zitat antworten Zitat
frankg

Registriert seit: 20. Mai 2003
Ort: Wetter
72 Beiträge
 
Delphi 7 Architect
 
#6

Re: Baumansicht

  Alt 6. Aug 2003, 11:38
Zitat von theomega:
Jauh, das mit dem Unique ist mir auch schon aufgefallen, das werde ich sofort ändern (müßen). Aber wie machst du diese tollen verhältnis-Diagramme?
Hallo TheOmega!

Die Verhältnisdiagramme heissen eigentlich ERD-Diagramme (Entity Relationship) (Okok, die Diagramme sind nicht 100% nach den ERD Richtlinien ). Die kann man ganz gut mit Microsoft Visio 2002 machen. Je nachdem welche Version Du von Visio verwendest ist das Programm auch dazu in der Lage aus den Diagrammen SQL-Scripte zu erzeugen, die Dir dann die Datenbank automatisch aufbauen, d.h. hier musst Du die Scripte nicht mehr per Hand erstellen sondern machst nur noch das Design der Datenbank (Nacharbeiten per Hand schadet aber nicht ).

Viele Grüsse

Frank
  Mit Zitat antworten Zitat
Benutzerbild von theomega
theomega

Registriert seit: 18. Jun 2002
684 Beiträge
 
#7

Re: Baumansicht

  Alt 6. Aug 2003, 17:13
Gut, die Sache funktioniert ganz gut, nur eine Sache stört mich noch: Bis jetzt werden ja Ordner ausgeblendet, wenn für sie nicht mindestens ein Eintrag in allen 4 Tabellen existiert. Wie bekomme ich es hin, das selbst wenn jetzt kein Konto-eintrag für eine Funktion existiert, trotzdem die Funktion zurückgegeben wird, dann ohne einen Eintrag für das Konto.

Hat das jetzt jemand verstanden? Und weiß jemand eine Lösung?
  Mit Zitat antworten Zitat
frankg

Registriert seit: 20. Mai 2003
Ort: Wetter
72 Beiträge
 
Delphi 7 Architect
 
#8

Re: Baumansicht

  Alt 6. Aug 2003, 17:52
Zitat von theomega:
Gut, die Sache funktioniert ganz gut, nur eine Sache stört mich noch: Bis jetzt werden ja Ordner ausgeblendet, wenn für sie nicht mindestens ein Eintrag in allen 4 Tabellen existiert. Wie bekomme ich es hin, das selbst wenn jetzt kein Konto-eintrag für eine Funktion existiert, trotzdem die Funktion zurückgegeben wird, dann ohne einen Eintrag für das Konto.
Hallo TheOmega!

Um Datensätze anzeigen zu lassen, die keinen Foreign Key Wert besitzen (d.h. bei denen dieser Wert NULL ist) muss man nun einen Outer Join verwenden. Der Outer Join nimmt alle Datensätze einer der beiden Tabellen (oder beider) Tabellen mit in die Ergebnisdatenmenge auf. Damit angegeben werden kann, welche Datensätze auch ohne FK in die Ergebnisdatenmenge sollen, wird eine Tabelle als linke und eine als rechte Tabelle bezeichnet (hängt von der Poisition der Tabelle in Bezug auf das Gleichheitszeichen innerhalb der Where-Klausel ab. Ein Right-Outer Join nimmt alle Datensätze, bei denen der FK Null ist der rechten Tabelle mit, ein Left-Outer Join nimmt alle Datensätze der linken Tabelle mit.
Unglücklicherweise unterscheidet sich hier die Syntax der einzelnen SQL-Dialekte (soweit zum Standard SQL). Codetechnisch sieht das ganze dann unter Oracle folgendermassen aus:

SQL-Code:
SELECT
  *
FROM
  SACHBUCH SB,
  GLIEDERUNG GL,
  FUNKTION FK,
  KONTO KO
WHERE
  (SB.SACHBUCH_ID = GL.SACHBUCH_ID) AND
  (GL.GLIEDERUNG_ID = FK.GLIEDERUNG_ID) AND
  (FK.FUNKTION_ID = KO.FUNKTION_ID (+));
In diesem Beispiel haben wir einen right Inner Join zwischen FK.FUNKTION_ID und KO.FUNKTION_ID definiert, d.h. es werden auch die Datensätze aus der Tabelle KONTO in die Ergebnisdatenmenge aufgenommen, die keinen Wert im Feld FUNKTION_ID besitzen.

Leider weiss ich nicht, wie genau man das unter Firebird syntaktisch formuliert. Ich tippe auf irgendwas wie:

  FK.FUNKTION RIGHT INNER JOIN KO.FUNKTION_ID Viele Grüsse

Frank
  Mit Zitat antworten Zitat
Benutzerbild von theomega
theomega

Registriert seit: 18. Jun 2002
684 Beiträge
 
#9

Re: Baumansicht

  Alt 6. Aug 2003, 18:01
Kann hier evtl jemand mit Interbase Kenntnissen nachhelfen, ich bekomms nicht hin mit dem Innter Join, wo muß das hin?
  Mit Zitat antworten Zitat
Benutzerbild von MrSpock
MrSpock
(Co-Admin)

Registriert seit: 7. Jun 2002
Ort: Owingen
5.865 Beiträge
 
Delphi 2010 Professional
 
#10

Re: Baumansicht

  Alt 7. Aug 2003, 22:07
Hallo Omega,

wenn du alle Datensätze aus Tabelle1 haben möchtest, auch dann, wenn die entsprechenden Daten in Tabelle2 stehen, benötigst du einen left outer join

SQL-Code:
SELECT a.name, b.projekt
FROM personen a
   LEFT OUTER JOIN projekte b
      ON a.id = b.mitarbeiter_id
Dieses Statement zeigt alle Mirarbeiter an, auch diese, die zur Zeit nicht an einem Projekt arbeiten. Es gibt auch noch einen FULL OUTER JOIN, der alle Datensätze beider Tabellen anzeigt. Den kannst du aber hier nicht gebrauchen.
Albert
Live long and prosper


MrSpock
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:04 Uhr.
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