mySQL Datenbank Design für verschachtelte, dynamische Navigation

S

sevY

Hi, ich komme nicht weiter…

Ich versuche gerade ein CMS als Frontend an dein DB Modell zu setzen und frage mich, wie ich die Queries machen soll…


Hier ist ein DB Modell, das ein Freund mir erstellte, mit dem er hoffte, das es gehen wird:

PHP:
#MySQL

CREATE TABLE `multiple` (
  `id` int(11) NOT NULL auto_increment,
  `parent_id` int(11) NOT NULL default '0',
  `date` int(11) NOT NULL default '0',
  `text` varchar(60) default NULL,
  `image` varchar(60) default NULL,
  `link` varchar(60) default NULL,
  PRIMARY KEY  (`id`)
) TYPE=MyISAM AUTO_INCREMENT=1 ;





Als Oberpunkte habe ich:

A B C D E F G

Jeder der Punkte hat Unterpunkte wie folgt:

a b c d e


Diese o.g. genannten Punkte sind alle fest und werden nicht erweitert.


Diese Punkte enthalten Unterpunkte, die dynamisch erweiterbar sein sollen

a b c d e


Also:

a1 a2 a3 a4 … ax

b1 b2 b3 b4 … bx

… … … … … …

Diese Unterpunkte enthalten wiederum Unterpunkte:

a1-1 a1-2 a1-3 a1-4 … a1x
a2-1 a2-2 a2-3 a2-4 … a2x

b1-1 b1-2 b1-3 b1-4 … b1x
b2-1 b2-2 b2-3 b2-4 … b2x

… … … … … …
… … … … … …


Und diese haben dann nocheinmal Unterpunkte.


a1-1-1 a1-1-2 a1-1-3 … a1-1-x
a1-2-1 a1-2-2 a1-2-3 … a1-2-x
… … … … …

a2-1-1 a2-1-2 a2-1-3 … a2-1-x
a2-2-1 a2-2-2 a2-2-3 … a2-2-x
… … … … …

b1-1-1 b1-1-2 b1-1-3 … b1-1-x
b1-2-1 b1-2-2 b1-2-3 … b1-2-x
… … … … …

b2-1-1 b2-1-2 b2-1-3 … b2-1-x
b2-2-1 b2-2-2 b2-2-3 … b2-2-x
… … … … …

… … … … …
… … … … …
… … … … …



Wie würde die Inhalte aussehen? Wie sieht zb die Query aus für 'b2-2-3' oder für 'b2-3' als Insert, Read, Update?


Fragen Fragen Fragen nichts als Fragen…


Liebe Grüße

Yves
 
Hallo Yves!

Also ich würde das Problem mit mindestens zwei Tabellen lösen. Ich hab jetzt nicht wirklich gross darüber nachgedacht. Aber ich versuche hier mal ein Beispiel zu geben

PHP:
CREATE TABLE `parent` (
  `parent_id` int(11) NOT NULL auto_increment,
  `parent_name` int(11) NOT NULL default '0',
  PRIMARY KEY  (`parent_id`)
) TYPE=MyISAM AUTO_INCREMENT=1 ;  

/*und für die eigentlichen Navi*/

CREATE TABLE `navi` (
  `id` int(11) NOT NULL auto_increment,
  `parent_id` int(11) NOT NULL default '0',
  `date` int(11) NOT NULL default '0',
  `text` varchar(60) default NULL,
  `image` varchar(60) default NULL,
  `link` varchar(60) default NULL,
  PRIMARY KEY  (`child_id`)
) TYPE=MyISAM AUTO_INCREMENT=1 ;

Die Abfrage kannst du dann wie folgt machen.

PHP:
$sql="
SELECT C.text, C.image, C.link, P.parent_name
FROM navi AS C
LEFT JOIN parent AS P ON C.parent_id = P.parent_id
";

Somit solltest du eine Tabelle in diesem Stil zurückbekommen:

Code:
| text | image | link | parent_name |
|------|--------|------|----------------|
| Seite 1 | bild.jpg | http://... | Seiten |

Verstehst du in etwa wie ich das meine?

Wenn du jetzt ein Parent setzen willst, musst du diesen in der parent Tabelle anlegen. Für die childs kannst du dann einfach die parent_id, welche erstellt wurde einfügen. Sollte so eigentlich klappen...

Nachtrag: Mit dem obigen Query werden alle Parents angezeigt, auch diese, welche keine childs haben. Willst du dass nur die Parents angezeigt werden, welche childs haben, musst du anstelle von LEFT JOIN einfach INNER JOIN verwenden.

Ich hoffe dir geholfen zu haben

Greets balu
 
Ist vielleicht ganz blöd: Kannst Du nicht einfach in der Tabelle noch drei Spalten anlegen?

Code:
Hauptpunkt  |  Unterpunkt1  |  Unterpunkt 2
------------|---------------|-----------------
       a    |       1       |                               <- Menüpunkt a-1
------------|---------------|-----------------
       c    |        2      |          3                   <- Menüpunkt c-2-3

Und dann machst Du Queries wie "SELECT […] WHERE Hauptpunkt=a AND Unterpunkt1=1 AND Unterpunkt2=''". Damit bekommst Du dann alle Punkte der ersten Unterebene von a.

Oder Du fragst gleich alles ab mit SELECT * und unterscheidest dann mit ner PHP-Funktion, welche Punkte wo Unterpunkte haben und angezeigt werden sollen.
 
Zuletzt bearbeitet:
Eine zweite Tabelle ist eigentlich nicht nötig. Einfach ein Feld "parentOf" oder sowas in die bestehende Tabelle einfügen. Darin wird ggf. die ID des übergeordneten Punkten gespeichert. Dann kann man leicht ermitteln ob es sich um einen Unter- oder Hauptpunkt handelt und zu welchem Hauptpunkt ein Unterpunkt gehört. Ich habe vor Ewigkeiten mal sowas gemacht. Der Code existiert leider nicht mehr.
 
Sehe ich genauso, ein Feld "parent" oder ähnlich in die ursprüngliche Tabelle einzufügen sollte reichen. Allerdings nicht, wenn ein Menüpunkt mehrere Väter haben kann. Das Problem an solchen Strukturen in MySQL ist, dass es keine rekursiven Abfragen erlaubt, im Gegensatz zu mächtigeren Datenbanken.

Wirkliche Probleme erhälst Du nicht beim Einfügen in den Baum, sondern beim Lesen und Aufbauen desselben in Bezug auf die Anzahl der Queries. Dafür gibt es meiner Ansicht nach 3 Möglichkeiten:
1. Einen Query pro Menüpunkt, um die Kinder herauszufinden. Das ist recht dreckig, da viel zu viele Queries.
2. Wenn der Baum auf- und zuklappbar sein soll, könntest Du bei Bedarf neue Queries absetzen, um die Unterpunkte zu einem Menüpunkt zu erhalten.
3. Das ganze Menü als Result Set holen und mit Hilfe von PHP (ich nehme an, das ist die Hostsprache) den Baum aufbauen. Mit einer klugen Vorsortierung durch die DB und einem vernünftigen Algorithmus könnte das Deine Lösung sein.

Ansonsten: Steig auf Oracle oder sowas um ;)))

@Jakob: Deine Lösung ist absolut nicht geeignet, da auf eine gewisse Anzahl an Untermenüpunkten beschränkt.
 
Zuletzt bearbeitet:
Dein Ansatz ist schon richtig und auch am flexibelsten.
Das einzige Problem ist dabei das auslesen des Baums, was ein wenig komplizierter wird, dafür kannst du aber sehr leicht Zweige verschieben.
Und Beim Löschen musst du dir Gedanken machen was du mit den Kindern des Knoten machst.

Bleibt dir nichts anderes als Rekursion fürs Auslesen übrig. Ob man das in von der Datenbank oder, wie Yankee sagt, aus dem Memory macht bleibt dir überlassen.

Ansonsten sehen die Querys ganz normal aus:
Du hast ja immer eine ID auf die du dich beziehen kannst.
 
Hier könnte diese Lösung wirklich elegant sein.
 
Zurück
Oben Unten