PHP Portal » PHP Forum » Entwicklung » MySQL, PostgreSQL und SQL-konforme Datenbanken » Baumstruktur mit menu_menu

[MySQL] Baumstruktur mit menu_menu 

von
Neuling
Zitat
Hallo Leute,

ich habe vor einigen Jahren mir ein Menü aus diesen Vorlagen gebastelt gehabt:
http://www.php- ... -am-besten.html

Meine SQL Abfrage:

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SELECT m2.menu_id, m2.file_name, m2.sort, m2.parent_id, m2.name FROM menu m LEFT JOIN menu_has_menu mm ON ( m.menu_id = mm.child_id ) LEFT JOIN menu m2 ON ( mm.menu_id = m2.parent_id ) LEFT JOIN menu m3 ON ( m.menu_id = m3.menu_id OR m.parent_id = m3.menu_id ) WHERE m3.file_name = '".$file_name."' OR m.parent_id = 0 GROUP BY m2.menu_id, m2.parent_id, m2.sort ORDER BY m2.parent_id, m2.sort

Code
1
2
3
4
5
6
7
8
9
10
CREATE TABLE IF NOT EXISTS `menu` ( `menu_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `parent_id` int(10) unsigned NOT NULL DEFAULT '0', `file_name` varchar(255) NOT NULL DEFAULT '', `name` varchar(255) NOT NULL DEFAULT '', `sort` int(10) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`menu_id`), UNIQUE KEY `file_name` (`file_name`), KEY `parent_id` (`parent_id`,`menu_id`) ) ENGINE=MyISAM;

Code
1
2
3
4
5
CREATE TABLE IF NOT EXISTS `menu_has_menu` ( `menu_id` int(10) unsigned NOT NULL DEFAULT '0', `child_id` int(10) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`menu_id`,`child_id`) ) ENGINE=MyISAM;


So nun bin ich zu der Annahme gekommen das die OR Bedingungen nicht gerade effektiv sind für die Abfragegeschwindigkeit. Da JOINS immer noch nicht meine Leidenschaft sind, wollte ich mal sehen ob mir da mal jemand in die richtige Richtung lenken kann. Eventuell müsste ich die menu_has_menu noch erweitern um auf die OR Bedingungen verzichten zu können.

Werbung

Re: Baumstruktur mit menu_menu 

von
Neuling
Zitat
Hier noch der Explain zum SQL Statement:

Code
1
2
3
4
1 SIMPLE m index parent_id parent_id 8 NULL 44 Using index; Using temporary; Using filesort 1 SIMPLE mm index NULL PRIMARY 8 NULL 77 Using index 1 SIMPLE m2 ref parent_id parent_id 4 msshop.mm.menu_id 5 1 SIMPLE m3 ALL PRIMARY NULL NULL NULL 44 Range checked for each record (index map: 0x1)

Re: Baumstruktur mit menu_menu 

von
the Boss
Zitat
abgesehen von deiner Query, ist eigentlich erstmal die Frage wichtig,
welches Ergebnis du haben möchtest. Eventuell läßt sich dann eine bessere
Abfrage konstruieren.

Re: Baumstruktur mit menu_menu 

von
Neuling
Zitat
Ok, also ziel ist die Ausgabe eines Menü in Baumstruktur das eine tiefe von bis zu drei Ebenen haben kann.

PHP Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$rows = mysql_num_rows($sql); while($set = mysql_fetch_array($sql)){ $result1[]=$set; } function &build_menu(&$result,&$rows,$cat,$parent=0,$level=0){ global $sl, $ses; $output = ''; for($i=0;$i<$rows;++$i){ if($result[$i]['parent_id']==$parent){ //code mal bereinigt $url = $sl.'/'.$result[$i]['file_name'].'/index.html'.$ses; $color = 'ml'; if($result[$i]['file_name'] == $cat){ $color = 'mlc'; } $output .= ' '.str_repeat('-',$level).' <a href="'.$url.'" class="'.$color.'">'.$result[$i]['name'].'</a>'; $output .= build_menu($result,$rows,$cat,$result[$i]['menu_id'],$level+1);
für die ungekürzte Fassung bitte einloggen


zusammengebaut wird es mit dieser Funktion.

Die Struktur kann dann nachher so zum Beispiel aussehen:

  • Ebene 1a
  • Ebene 1b
  • - Unterebene 2a
  • - Unterebene 2b
  • - Unterebene 2c
  • -- Subunterebene 3a
  • -- Subunterebene 3b
  • - Unterebene 2d
  • - Unterebene 2e
  • Ebene 1c
  • Ebene 1d

Re: Baumstruktur mit menu_menu 

von
the Boss
Zitat
wenn du eine feste Maximaltiefe hast dann brauchst du die menu_has_menu nicht.
Da reicht ein einfaches

Code
1
2
3
4
5
SELECT ... FROM menu a LEFT JOIN menu b ON ( a.menu_id = b.parent_id ) LEFT JOIN menu c ON ( b.menu_id = c.parent_id ) WHERE a.parent_id = 0


die menue_has_menu wird nur benötigt, wenn die Anzahl der Ebenen unbekannt/unbegrenzt ist.

Re: Baumstruktur mit menu_menu 

von
Neuling
Zitat
ein Problem könnte dann irgendwann werden, wenn ich statt den drei Ebenen noch eine vierte hinzufügen will. Ist zwar in den letzten Jahren nie vorgekommen und ein Bedarf sehe ich auch noch nicht. Nur ausschließen kann ich es irgendwie nicht.

Aber erstmal egal, ok jetzt muß ich die Joins nur noch verstehen

Code
1
2
3
4
5
6
7
SELECT a.name FROM menu a //erste ebene LEFT JOIN menu b ON ( a.menu_id = b.parent_id ) //zweite ebene LEFT JOIN menu c ON ( b.menu_id = c.parent_id ) //dritte ebene WHERE a.parent_id = 0


Angenommen ich rufe den Link Subunterebene3 auf.

Where file_name = 'Subunterebene3'

Dann schaue ich in die Spalte file_name wo der Begriff vorkommt (man kann das auch mit IDs machen, ist aber wegen Seourls so bei mir gestaltet).
Nun wird von diesem Eintrag der parent_id Wert genommen und alle Einträge die den gleichen Wert in der parent_id Spalte haben geholt, dann gehe ich schauen ob ein menu_id Eintrag mit dem Wert vorliegt und wenn ja hole ich von diesem Eintrag ebenfalls alle mit diesem parent_id Wert, sehe ich das so richtig.

Re: Baumstruktur mit menu_menu 

von
the Boss
Zitat
du willst also von jedem Punkt aus, alle direkt übergeordneten Punkte,
den kompletten Baum darunter, sowie alle Nebenzweige bei den darüber geordneten?
Also wie eine minimal aufgeklappte Ansicht im Dateibaum - siehe Anhang?

Re: Baumstruktur mit menu_menu 

von
Neuling
Zitat
Ja genau, so meinte ich das eigentlich.

Re: Baumstruktur mit menu_menu 

von
the Boss
Zitat
sollte so gehen

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SELECT d.menu_id, d.name, d.parent_id, d.sort // Ausgangspunkt FROM menu a // alle direkten Eltern und alle Kinder INNER JOIN menu_has_menu b ON ( a.menu_id = b.menu_id OR a.menu_id = b.parent_id ) // dazu wieder das Menü INNER JOIN menu c ON ( b.menu_id = c.menu_id ) // und nochmal die Kinder (für die Nebenzweige) INNER JOIN menu d ON ( c.parent_id = d.parent_id ) // gegebener Knoten WHERE a.menu_id = [aktuellerPunkt] ORDER BY d.sort ASC

musst das Ganze aber über eine rekursive Funktion ausgeben.

PS: wenn du die menu Tabelle noch um das Level (Baumtiefe) erweiterst,
dann kannst du auch die Tiefe der automatisch aufgeklappten Kinder bestimmen.

Schnellantwort

ähnliche Themen

Baumstruktur speichern