AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken Delphi Master-Detail mit many-to-many Relation
Thema durchsuchen
Ansicht
Themen-Optionen

Master-Detail mit many-to-many Relation

Ein Thema von Stevie · begonnen am 12. Aug 2011 · letzter Beitrag vom 15. Aug 2011
Antwort Antwort
mkinzler
(Moderator)

Registriert seit: 9. Dez 2005
Ort: Heilbronn
39.880 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: Master-Detail mit many-to-many Relation

  Alt 12. Aug 2011, 16:53
Einfach einen Join verwenden
SQL-Code:
select
    b.*
from
    books b
where
    b.id in ( select book from BookAuthor where autor = :autor);
Markus Kinzler
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.052 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#2

AW: Master-Detail mit many-to-many Relation

  Alt 12. Aug 2011, 17:28
Wie man die Daten per SQL erhält, weiß ich sehr wohl

Ich habe drei Datasets, welche den Inhalt dieser Tabellen liefern. ... Diese Vorgaben sind unveränderbar.
Einfach einen Join verwenden
SQL-Code:
select
    b.*
from
    books b
where
    b.id in ( select book from BookAuthor where autor = :autor);
Mit diesem Ansatz hätte ich dann n+1 Abfragen (n = Anzahl der Authoren). Ziemlich unpraktisch. Von den redundanten Records bei Büchern, die mehr als einen Author haben, mal nicht zu reden.

Ziel ist es, einen universellen Ansatz zu haben, wie man 2 Datasets, die über ein 3. Dataset in einer many-to-many Beziehung stehen, in einer Hierarchie (z.B. treeview) darstellen kann. Die eigentliche Darstellung ist erstmal unerheblich, sondern nur die Aufbereitung bzw die Verbindung der Datasets zu regeln.

Ich greif nochmal mein Beispiel mit den Büchern auf:

Hätte ich ein Datenmodell, wo ein Buch nur einen Author haben kann (also ein AuthorId Feld in der Books Tabelle), dann würde man das Authors Dataset als Master nehmen und das Books Dataset als Detail und diese über AuthorId verbinden.

Da ich aber nun 2 Ebenen von 1 zu n Beziehungen habe würde das wie folgt aussehen:
Master1: Authors
Detail1: BookAuthors (DetailKey = AuthorId, MasterKey = AuthorId

Master2: BookAuthors
Detail2: Books (DetailKey = BookId, MasterKey = BookId)

Aus diesen 2 1-to-n Beziehungen möchte ich aber wieder eine n-to-n Beziehung bauen.
Das sähe etwa so aus:
Master: Authors
Detail: Books (DetailKey = BookId, MasterKey = bookauthors.bookid where bookauthors.authorid = authors.authorid)

Hoffe, das Problem ist etwas klarer geworden.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight

Geändert von Stevie (12. Aug 2011 um 17:32 Uhr)
  Mit Zitat antworten Zitat
WM_CLOSE

Registriert seit: 12. Mai 2010
Ort: königsbronn
398 Beiträge
 
RAD-Studio 2009 Pro
 
#3

AW: Master-Detail mit many-to-many Relation

  Alt 12. Aug 2011, 19:21
Ich habe das jetzt mal so verstanden:

Du hast eine Tabell Bücher
Buchdaten | BuchId

Eine Tabelle Autoren
AutorId | Autordaten

Und eine Tabelle mit den Verweisen
BuchId | AutorId

Du willst z.B. alle Bücher eines Autors haben:
Code:
SELECT Buchdaten FROM BuchTabelle JOIN VerweisTabelle ON (BuchTabelle.BuchId=VerweisTabelle.BuchId) WHERE (VerweisTabelle.AutorId=AutorId)
Ohne Gewähr, dass das Query richtig rum ist
Delphi programming
  Mit Zitat antworten Zitat
FredlFesl

Registriert seit: 19. Apr 2011
293 Beiträge
 
Delphi 2009 Enterprise
 
#4

AW: Master-Detail mit many-to-many Relation

  Alt 12. Aug 2011, 20:54
Lies doch einfach die drei Tabellen in den Speicher.
Du hast doch eine Master-Detail-Beziehung. Dann zwei Grids, links Autoren, rechts die Bücher, Filter in den Büchern setzen, fertig.
Gut der Filter in der Bücher-Tabelle ist nicht ganz trivial, aber mit einer Hashmap wirklich schnell umgesetzt.
Sei BooksAndAuthors die Relationstabelle mit zwei Spalten (na gut, 3, aber den PK vergessen wir) "AuthorID" und "BookID".
Dann erstellst Du eine <Int, List<Int>>Hashmap. Key ist die AuthorID und pro Author wird eine Liste der BookIDs in der Map abgelegt.
Wenn du durch die Autoren scrollst, dann filterst Du die Bücher einfach jeweils neu, indem Du beim Scrollen die zum fokussierten Autoren-datensatz gehörende jeweilige BookID-Liste aus der Hashmap holst und dann nur die Bücher anzeigst, die in der Liste sind.

Das geht auch ohne Hashmap, weil eine gute DB das auch (fast) in Echtzeit hinbekommt. Bei jedem scrollen in der Autorentabelle einfach ein
Code:
Select b.* from Books b join BooksAndAuthors ba on b.bookid = ba.bookID where ba.AuthorID = :AuthorID
absetzen... des ist fast genauso schnell. Cachen kann man das auch noch, falls Du die Amerikanische Staatsbibliothek mit der Software ausrüsten willst...

Oder hab ich dein Problem nicht verstanden?
Das Bild hängt schief.

Geändert von FredlFesl (12. Aug 2011 um 21:01 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.052 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#5

AW: Master-Detail mit many-to-many Relation

  Alt 12. Aug 2011, 22:07
Ums nochmal klar zu machen: Ich brauch und will kein SQL Statement.

Ich möchte eine Möglichkeit haben, beliebige Datenmengen (Datasets), die in Relationen stehen, hierarchisch darzustellen und weitergehend auch beliebig gruppieren zu können.

Der Ansatz mit der Hashmap geht schonmal in eine brauchbare Richtung. Allerdings will ich meine Daten nicht in Grids anzeigen, sondern in einem einzigen Tree Control. Dazu möchte ich aber die Datenstruktur nicht komplett auf Objektebene oder so neu aufbauen, sondern beim Aufbau der Nodes die Daten über eine vorher festgelegte Struktur aus den Datasets auslesen.
Bei dem Bücher Beispiel wäre dass in der ersten Ebene Authors und zweite Ebene Books. Die Relation dieser beiden Ebenen (also, welche Bücher unter welchem Author aufgelistet werden) wird dann über die many to many Relation abgebildet. Das ganze soll so flexibel sein, dass ich z.b. das ganze auch umgruppieren kann und z.B. in der ersten Ebene das Genre, zweite Ebene Bücher und dritte Ebene Authoren abbilde.

Das ganze wird wohl auf ein Filtern des untergeordneten Datasets der jeweils im Aufbau befindlichen Node hinauslaufen.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
FredlFesl

Registriert seit: 19. Apr 2011
293 Beiträge
 
Delphi 2009 Enterprise
 
#6

AW: Master-Detail mit many-to-many Relation

  Alt 13. Aug 2011, 08:28
Hi. Das SQL-Statement war eher für andere Leser gedacht und diente der Verdeutlichung meiner Idee. Das Du SQL kannst, hast Du ja nun bereits erwähnt.

Ich sitze derzeit an einem ähnlichen Problem. Bei mir geht es auch nur um die Darstellung. Ich verwende das TcxGrid, womit man ganz brauchbar gruppieren kann. Ich stelle also im Grid die komplette Autor-Bücher Beziehung dar (Autoren und Bücher kommen dann mehrfach vor). Ich kann angeben, das in einer Spalte ein mehrfach hintereinander vorkommender Wert nur 1x dargestellt wird.

Sortiere ich nach Autoren, erhalte ich pro Autor (linke Spalte) alle Bücher, etwa so:
Code:
Autor v| Buch
===================
Autor-1 | Buch-1-A1
        | Buch-2-A1
-------------------
Autor-2 | Buch-1-A2
        | Buch-2-A1   <<<--- Achtung, Buch kommt doppelt vor
Sortiere ich nach Büchern, erhalte ich:
Code:
Autor  | Buch   v
===================
Autor-1 | Buch-1-A1
-------------------
Autor-2 | Buch-1-A2
-------------------
Autor-1 | Buch-2-A1
Autor-2 |
Das ist ja sowas wie ein Baum, nur als Grid.

Google mal nach "Pivot-Grid" und schau dir diese Look&Feel Ansätze an. Im Grunde genommen ist das etwas Ähnliches (zumindest vom der Problematik, das man hierarchische Abhängigkeiten konfigurieren und darstellen muss).
Das Bild hängt schief.
  Mit Zitat antworten Zitat
WM_CLOSE

Registriert seit: 12. Mai 2010
Ort: königsbronn
398 Beiträge
 
RAD-Studio 2009 Pro
 
#7

AW: Master-Detail mit many-to-many Relation

  Alt 13. Aug 2011, 08:47
Zu langsam, aber vielleicht hilft es ja.

Dann mach doch noch statt dem WHERE Filter noch nen Join. Dann hast du alles was du brauchst in einem Query.

Autordaten Verweis(nicht sichtbar) Buchdaten
Schumann 1 1 Delphi für Kids
Schumann 1 2 Spieleprog. m. C++
Spolwing 2 3 Class in a Box Delphi
Doberenz 3 4 Borland Delphi 7...
Gewinnus 4 4 Borland Delphi 7...

Nun tue für jede Zeile:
-Suche den Node mit der Id des Autors
-Speichere ihn in der Variable Node
-Solltest du ihn nicht gefunden haben
-Erstelle einen neuen Node mit den Autordaten und speichere ihn in der Variablen Node
-Trage nun unter dem Node aus Variable Node
einen neuen Node mit den Bücherdaten ein
Delphi programming
  Mit Zitat antworten Zitat
Benutzerbild von Stevie
Stevie

Registriert seit: 12. Aug 2003
Ort: Soest
4.052 Beiträge
 
Delphi 10.1 Berlin Enterprise
 
#8

AW: Master-Detail mit many-to-many Relation

  Alt 13. Aug 2011, 12:44
Manchmal frag ich mich hier echt, wozu man irgendwelche Vorgaben macht und auch noch erwähnt, dass diese unveränderlich sind, wenn manche dann andauernd mit Alternativen um die Ecke kommen. Ich kenne die Alternativen, es über einen Join in eine Datenmenge zu bekommen, und diese wieder auseinander zu nehmen. Ist aber hier nicht gefragt.

@FredlFesl: Ja, das Prinzip des Pivot Grids kommt meinem Vorhaben in etwa nahe, ist mir aber zu starr an diese spezielle Komponente gebunden. Ich vermute auch, dass man im PivotGrid auch nur eine Datenmenge angeben kann, die dann so aufbereitet wird oder? Mir geht es wirklich darum die n-zu-n Beziehung (die ja eigentlich 2mal eine 1-zu-n Beziehung ist) so aufzulösen, dass ebend nicht diese extra Ebene entsteht, die durch die 2 1-zu-n Beziehungen entsteht.
Stefan
“Simplicity, carried to the extreme, becomes elegance.” Jon Franklin

Delphi Sorcery - DSharp - Spring4D - TestInsight
  Mit Zitat antworten Zitat
jobo

Registriert seit: 29. Nov 2010
3.072 Beiträge
 
Delphi 2010 Enterprise
 
#9

AW: Master-Detail mit many-to-many Relation

  Alt 15. Aug 2011, 10:34
Warum regst Du Dich so über "SQL-Antworten" auf, wenn Du Deine Anfrage unter "Datenbank" postest?
und ich frage mich außerdem, was eigentlich Deine Frage ist.

Meines Wissens gibt es Komponenten, die eine beliebige Datenmenge beliebig gruppieren können. Bei normalisierten Daten kann das sinnvollerweise nur auf Attributen erfolgen, die eine Art Klassifizierung darstellen, also irgendwie mehrfach auftauchen. Klar, ohne "mehrfach" keine Gruppierung.
Stichwort wäre jedoch "normalisiert" bzw denormalisiert. Hast Du mehrere Mengen, 2, 3, 4 .. könntest du den umgekehrten Weg gehen, die Mengen alle zusammenbringen, also denormalisieren und dann auf dem großen Datenwürfel nach Herzenslust gruppieren (Stichwort Pivot ist ja schon gefallen). Das bringt natürlich die bekannten Probleme mit sich, wenn die Datenmengen groß werden. Und das willst Du ja anscheinend auch nicht.

Sollen die Mengen disjunkt bleiben, könnte man etwa folgendes Standardvorgehen wählen:
Gruppierungsmenge 1 festlegen
Verknüpfungsmenge 2 festlegen
Detailmenge 3 festlegen

1 wird nach Gruppierungsattribut sortiert,
Menge 2 wird wie 1 plus gewünschter Detailordnung (Hier schon ggF weitere Unter Gruppierung berücksichtigen)
3 wird nach Detailordnung von 2 sortiert (evtl auch egal, muss wahrscheinlich sowieso located werden)

Für alle 3 Mengen die Verknüpfungsattribute definieren

Dann Treeview oder Liste aufbauen:
Erste Eben über Menge 1 füllen (komplett)
Dann je nach Bedarf und Aufwand ("onexpand" oder ebenfalls alles ) Menge 2 und 3 durchsteppen bzw. "locaten" und entsprechende Nodes an Ebene 1 anhängen.

Bei disjunkten Basismengen taugt das Verfahren allerdings nur zur Herstellung der Hierarchie, die tatsächlich in den (mglw. sauber normalisierten) Basismengen abgebildet ist. Gruppierung über beliebige Klassenattribute wie oben genannt funktioniert so nicht ohne weiteres (Stichwort doppelte Elemente/Mehrfachnennung), zumindest habe ich spontan das Gefühl, dass das noch etwas aufwändiger wäre.
Gruß, Jo
  Mit Zitat antworten Zitat
FredlFesl

Registriert seit: 19. Apr 2011
293 Beiträge
 
Delphi 2009 Enterprise
 
#10

AW: Master-Detail mit many-to-many Relation

  Alt 15. Aug 2011, 12:53
Ich vermute auch, dass man im PivotGrid auch nur eine Datenmenge angeben kann
Ja, das ist das Wesen eines Datastore/Datawarehouse. Millionen/Milliarden von Daten lassen sich nicht mehr performant in normalisierten Tabellen halten, die verknüpft werden. Ein Datastore besteht aus einer Tabelle, bei denen vielleicht noch einzelne Dimensionen mit einer Kindtabelle verknüpft sind (z.B. Zeitstempel). Diese Kindtabellen sind aber allesamt im Speicher der Datamining-Anwendung, sodaß die Verknüpfung in-Memory stattfindet.

Um also deine Frage zu beantworten: Ich würde die n:m-Beziehung per SQL-JOIN auflösen, mir eine einzige Tabelle einlesen und die Gruppierung über ein Pivot-Grid oder etwas selbstgestricktes realisieren. Das Selbstgestrickte hat den Vorteil, auf die Besonderheiten deiner Datenmenge bzw. Anwendung besser eingehen zu können. Ein Pivot-Grid hat den Vorteil, das es schon fix-und-fertig ist... Fast-Report hat z.B. eine Pivot-Komponente, und der gute alte TDescision-Cube ist mit wenigen Handgriffen von der BDE befreit. Ob das allerdings genau das ist... frage ich mich auch gerade... Du willst ja gar nicht mit den Aggregatmöglichkeiten herumspielen... oder doch?

Man muss die Daten im Übrigen nicht komplett im Speicher halten. Wenn man sich auf die 'abstrakte' Sicht auf die Daten festgelegt hat (das ist ja das, wonach du u.a. suchst), kann man mit Cache, "SELECT DISTINCT" etc. durchaus eine Pufferungsebe implementieren..

Desweiteren sind auch die Gruppierungsmöglichkeiten von nativem SQL nicht zu unterschätzen. Das kommt allerdings erst dann zum tragen, wenn viele Datensätze einer Tabelle stark verdichtet werden müssen.

Und was die performante Darstellung anbelangt: Ich habe mir angewöhnt, die Daten schnellstmöglich aus dem TDataset herauszulösen und in Hashmaps oder Tries zu stopfen. Erst damit ist eine verzögerungsfreie Darstellung/Umgruppierung möglich.
Das Bild hängt schief.

Geändert von FredlFesl (15. Aug 2011 um 12:56 Uhr)
  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 17:51 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz