Beziehungen suchen

LL0rd

Erfahrenes Mitglied
Hallo,

ich habe ein Programm zur grafischen Auswertung entwickelt. Die grafischen Elemente werden nach der Auswertung in eine Datenbank geschrieben. Und zwar aufgeteilt auf zwei Tabellen.

Tabelle a) Beinhaltet die ID des Elementes, einen Namen sowie ein paar andere wie die Bewertung

Tabelle b) Enthällt die Punkte aller Elemente.

Nun möchte ich wissen, ob es einen / zwei / xxx Wege von Element 1 zu Element 2 gibt. Z.B. Element 1 ist über Element 34, Element 87, Element 90 -> Element 2 erreichbar. Quasi das gleiche Prinzip, wie auch bei OpenBC verwendet wird. Doch wie kann ich Effektiv so eine Kette aus MySQL rauskitzeln?
 
Hallo,

sofern du die maximale Anzahl an Schritten, durch die du suchen möchtest, konstant halten kannst (z.B. 6) wäre ein statisches SQL mit Unions und Self-Joins eine mögliche Lösung.

Ich gebe jetzt mal folgende fiktive Tabellenstruktur vor für die Punktepaare: (für deine Tabelle von Punkten/Verbindungen):

SQL:
Create table connections (
  start  integer(4),
  target integer(4)
);

Das einfachste was eintreten kann, wäre ja dass zwei Elemente/Punkte direkt miteinander verbunden sind. In dem Fall reicht eine ganz normale Abfrage ohne Joins.

SQL:
select conn.start, 
       conn.target, 
  from connections conn
 where conn.start  = $startwert
   and conn.target = $endwert

Für den Fall, dass zwei Elemente über einen Punkt miteinander verbunden sind (egal welcher), würdest du eine Abfrage mit einem Self-Join nutzen. Hierbei würde in "conn2.start" der Zwischenpunkt stehen.

SQL:
select conn1.start,
       conn2.start,
       conn2.target
  from connections conn1,
       connections conn2
 where conn1.target = conn2.start  
   and conn1.start  = $startwert
   and conn2.target = $endwert

Und für den Fall, dass genau zwei Stationen zwischen dem Start- und Endpunkt liegen kann die Query folgendermassen aussehen.
In dieser Query stehen in conn2.start und conn3.start die jeweiligen Zwischenpunkte.

SQL:
select conn1.start,
       conn2.start,
       conn3.start,
       conn3.target
  from connections conn1,
       connections conn2,
       connections conn3
 where conn1.target = conn2.start
   and conn2.target = conn3.start
   and conn1.start  = $startwert
   and conn3.target = $endwert

und so weiter für mehr Zwischenschritte/-punkte.

Um das ganze jetzt ein wenig aufzubereiten und mehrere mögliche Fälle gleichzeitig zu untersuchen, also alle Wege anzuzeigen, die ohne einen, mit genau einem oder mit genau zwei Zwischenschritten zum Ziel führen, kann man ein UNION ALL, eine Supportfunktion (concat_ws) und eine zusätzliche Spalte nutzen, z.B. so:

SQL:
select concat_ws(' => ', conn.start, conn.target) AS pfad, 
       0 AS anz_schritte
  from connections conn
 where conn.start  = $startwert
   and conn.target = $endwert
UNION ALL 
select concat_ws(' => ', conn1.start, conn2.start, conn2.target),
       1
  from connections conn1,
       connections conn2
 where conn1.target = conn2.start  
   and conn1.start  = $startwert
   and conn2.target = $endwert
UNION ALL
select concat_ws(' => ', conn1.start, conn2.start, conn3.start, conn3.target),
       2
  from connections conn1,
       connections conn2,
       connections conn3
 where conn1.target = conn2.start
   and conn2.target = conn3.start
   and conn1.start  = $startwert
   and conn3.target = $endwert

Die weiteren Joins zu den Daten der einzelnen Punkte hab ich jetzt mal aussen vorgelassen.

Eine Alternative wäre vielleicht noch eine Stored Procedure / Function.

Markus
 
Zuletzt bearbeitet:
Hi,

danke für deinen Tipp, allerdings geht bei vielen Einträgen die Geschwindigkeit fast gegen Null. Ich kann mir irgendwie kaum vorstellen, dass OpenBC / Xing auf die gleiche Art und Weise beziehungen sucht.
 
Hallo,

danke für deinen Tipp, allerdings geht bei vielen Einträgen die Geschwindigkeit fast gegen Null. Ich kann mir irgendwie kaum vorstellen, dass OpenBC / Xing auf die gleiche Art und Weise beziehungen sucht.

Das ganze war eher als Beispiel genannt und nicht als fertige Lösung. Ausserdem kenn ich OpenBC nicht. Es gibt einige Algorithmen, die das Abbilden solcher Relationen mittels einfacher Tabellenstrukturen kennen und damit auch viel schneller sind und auch in MySQL zu realisieren sind. Ich hatte dir ja den Hinweis gegeben, evtl. eine Stored Procedure in Erwägung zu ziehen um das ganze zu kapseln. Self-Joins waren sind nur ein Start, falls du gar keine Idee hast, wie man so etwas abbilden kann.

Markus
 
Das ganze war eher als Beispiel genannt und nicht als fertige Lösung. Ausserdem kenn ich OpenBC nicht. Es gibt einige Algorithmen, die das Abbilden solcher Relationen mittels einfacher Tabellenstrukturen kennen und damit auch viel schneller sind und auch in MySQL zu realisieren sind. Ich hatte dir ja den Hinweis gegeben, evtl. eine Stored Procedure in Erwägung zu ziehen um das ganze zu kapseln. Self-Joins waren sind nur ein Start, falls du gar keine Idee hast, wie man so etwas abbilden kann.

Hi,

das ganze sollte kein Vorwurf sein, dass deine Lösung schlecht ist oder nicht funktioniert. Das Problem ist aber wiegesagt die Performance, denn mysql braucht für die Joins wirklich extrem lange. Auf eine ähnliche Idee bin ich nämlich auch gekommen, dachte aber, dass es ähnlich wie in der Lösung von Tom eine einfachere xSQL eigene Methode dafür gibt.

@Tom
Funktioniert deine Lösung mit SYS_CONNECT_BY_PATH auch mit der express Version?
 
Hallo,

ja das funktioniert auch in der Express Version... wobei Oracle aber nicht empfiehlt die Express Version Produktiv einzusetzen...

Gruß Tom
 
Hallo,

der Grund weswegen Oracle nicht empfiehlt die Express Version einzusetzen ist der, dass dafür keine Patches herausgegeben werden. Bzw. die Patches der Standard / Enterprise Version nicht kompatibel zur Express Version sind. Ein Testsystem kannst du ja mal in einerVMWare hochziehen und schauen wie du das abgeschottet bekommst...

Postgresql bietet fast genau die gleiche Funktionionalität wie Oracle und ist Kostenlos... wäre also eine weitere Alternative...
http://linuxfr.org/~skc/8052.html

Für die DB2 wird die Lösung IMHO etwas fummeliger, sollte sich aber mit Rekursiven SQL (WITH...) lösen lassen.

schau mal hier:
http://www.ibm.com/developerworks/db2/library/techarticle/0307steinbach/0307steinbach.html
http://www.swissql.com/products/oracle-to-db2/oracle-to-db2.html

Gruß Tom
 

Neue Beiträge

Zurück