2010-09-03 6 views
7

Ich habe diese Tabelle:Wie generiert man eine Baumansicht aus dieser Ergebnismenge basierend auf dem Tree Traversal-Algorithmus?

CREATE TABLE `categories` (
    `id` int(11) NOT NULL auto_increment, 
    `category_id` int(11) default NULL, 
    `root_id` int(11) default NULL, 
    `name` varchar(100) collate utf8_unicode_ci NOT NULL, 
    `lft` int(11) NOT NULL, 
    `rht` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `category_id` (`category_id`), 
    KEY `lft` (`lft`,`rht`), 
    KEY `root_id` (`root_id`) 
) 

auf diese Frage basiert: Getting a modified preorder tree traversal model (nested set) into a <ul>

Der Unterschied ist, dass ich viele Bäume in einer Tabelle haben. Jede Zeile hat einen Fremdschlüssel, der das übergeordnete Element und das oberste übergeordnete Element darstellt: category_id und root_id. Ich habe auch die LFT und rht Felder auf der Grundlage dieses Beispiel: http://articles.sitepoint.com/article/hierarchical-data-database/2

Auf der Grundlage dieser Zeilen:

INSERT INTO `categories` VALUES(1, NULL, NULL, 'Fruits', 1, 14); 
INSERT INTO `categories` VALUES(2, 1, 1, 'Apple', 2, 3); 
INSERT INTO `categories` VALUES(3, 1, 1, 'Orange', 4, 9); 
INSERT INTO `categories` VALUES(4, 3, 1, 'Orange Type 1', 5, 6); 
INSERT INTO `categories` VALUES(5, 3, 1, 'Orange Type 2', 7, 8); 
INSERT INTO `categories` VALUES(6, 1, 1, 'Pear', 10, 11); 
INSERT INTO `categories` VALUES(7, 1, 1, 'Banana', 12, 13); 
INSERT INTO `categories` VALUES(8, NULL, NULL, 'Eletronics', 1, 14); 
INSERT INTO `categories` VALUES(9, 8, 8, 'Cell Phones', 2, 3); 
INSERT INTO `categories` VALUES(10, 8, 8, 'Computers', 4, 9); 
INSERT INTO `categories` VALUES(11, 10, 8, 'PC', 5, 6); 
INSERT INTO `categories` VALUES(12, 10, 8, 'MAC', 7, 8); 
INSERT INTO `categories` VALUES(13, 8, 8, 'Printers', 10, 11); 
INSERT INTO `categories` VALUES(14, 8, 8, 'Cameras', 12, 13); 

Wie kann ich eine ordened Liste zu erstellen, diesen Stammbaum darstellt?

mit dem SQL-Gebrüll:

SELECT c. * , (COUNT(p.id) -1) AS depth 
FROM `categorias` AS p 
CROSS JOIN categories AS c 
WHERE (
c.lft 
BETWEEN p.lft 
AND p.rht 
) 
GROUP BY c.id 
ORDER BY c.lft; 

Ich habe dieses Ergebnis:

alt text

Wie Sie sehen können, ich brauche auch von root_id zu bestellen, so dass ich die richtigen erzeugen kann Baum.

Gibt es nach dem Baum auch eine Möglichkeit, jeden Knoten nach seinem Namen zu sortieren?

Antwort

0

Ich habe es.

Alles, was Sie tun müssen, ist root_id auf die obersten Eltern zu setzen, damit Sie ORDER BY korrekt sortieren können.

Mit der Abfrage unten kann ich Bäume separeted haben, und uptade nur der Baum, der ich arbeite:

SELECT c . * , count(p.id) AS depth 
FROM `categories` c 
CROSS JOIN categories p 
WHERE (
c.lft 
BETWEEN p.lft 
AND p.rht 
) 
AND c.root_id = p.root_id 
GROUP BY c.id 
ORDER BY c.root_id, c.lft 
2

Wie Sie sehen können, muss ich auch von root_id bestellen, damit ich den richtigen Baum erzeugen kann.

Wenn Sie das verschachtelte Baummodell erstellen, machen Sie niemals Duplikate unter lft und rgt. In der Tat sollten Sie sie eindeutig erklären. In Ihrem Datenmodell überschneiden sich die Sätze für die Kategorien 1 und 8. Say, 1 bis 14 werden beide für die Artikel 1 und 8 verwendet.

sie mit diesen Werten ersetzen:

INSERT INTO `categories` VALUES(1, NULL, NULL, 'Fruits', 1, 14); 
INSERT INTO `categories` VALUES(2, 1, 1, 'Apple', 2, 3); 
INSERT INTO `categories` VALUES(3, 1, 1, 'Orange', 4, 9); 
INSERT INTO `categories` VALUES(4, 3, 1, 'Orange Type 1', 5, 6); 
INSERT INTO `categories` VALUES(5, 3, 1, 'Orange Type 2', 7, 8); 
INSERT INTO `categories` VALUES(6, 1, 1, 'Pear', 10, 11); 
INSERT INTO `categories` VALUES(7, 1, 1, 'Banana', 12, 13); 
INSERT INTO `categories` VALUES(8, NULL, NULL, 'Eletronics', 15, 29); 
INSERT INTO `categories` VALUES(9, 8, 8, 'Cell Phones', 16, 17); 
INSERT INTO `categories` VALUES(10, 8, 8, 'Computers', 19, 24); 
INSERT INTO `categories` VALUES(11, 10, 8, 'PC', 20, 21); 
INSERT INTO `categories` VALUES(12, 10, 8, 'MAC', 22, 23); 
INSERT INTO `categories` VALUES(13, 8, 8, 'Printers', 25, 26); 
INSERT INTO `categories` VALUES(14, 8, 8, 'Cameras', 27, 28); 

Sie müssen jetzt nicht auf root_id bestellen.

Auch, nach dem Baum, gibt es eine Möglichkeit, jeden Knoten nach Namen zu bestellen?

Kein einfacher Weg, es sei denn, Sie fügen die Knoten in der Namensreihenfolge von Anfang an ein. Geschwister mit den größeren name sollte größer haben lft und rgt:

INSERT INTO `categories` VALUES(1, NULL, NULL, 'Fruits', 1, 14); 
INSERT INTO `categories` VALUES(2, 1, 1, 'Apple', 2, 3); 
INSERT INTO `categories` VALUES(7, 1, 1, 'Banana', 4, 5); 
INSERT INTO `categories` VALUES(3, 1, 1, 'Orange', 6, 11); 
INSERT INTO `categories` VALUES(4, 3, 1, 'Orange Type 1', 7, 8); 
INSERT INTO `categories` VALUES(5, 3, 1, 'Orange Type 2', 9, 10); 
INSERT INTO `categories` VALUES(6, 1, 1, 'Pear', 12, 13); 

Ein verschachtelter Baum nur eine implizite Ordnung haben kann.

Es gibt auch eine Art und Weise Adjazenzliste in MySQL abfragen:

, aber Sie werden eine zusätzliche einmalige Bestellung Spalte erstellen, wenn Sie auf etwas bestellen möchten sonst als id.

Sie können auch diesen Artikel lesen möchten:

, die zeigt, wie zu speichern und Abfrage verschachtelt Sätze effizienter.

+0

Danke, werde ich diese Zeilen lesen und versuchen. Obwohl ich mich fragte, ob es nicht einen Weg gibt, wiederholt lft und rht zu halten, da ich einen Weg habe, zu unterscheiden (root_id). Ich habe bereits eine Abfrage mit etwas wie: WHERE root_id = 1 OR id = 1 ORDER BY lft erreicht, um einen der Bäume (aber nicht alle) zu erhalten. Das ist wirklich der falsche Weg? Auch habe ich die root_id als Referenz, wenn Sie die rebuild_tree() -Methode verwenden, die unter diesem Link aufgeführt ist http://articles.sitepoint.com/article/hierarchical-data-database/3 So funktioniert alles einwandfrei außer der SELECT für ordentierte Listen. –

+0

Wenn ich Ihre Schritte befolge, wie kann ich die Funktion rebuild_tree() ändern, um nur einen Baum und nicht alle neu zu erstellen? Da ich root_id entfernen werde? –

+0

Wenn Sie die Bäume immer trennen (wie bei WHERE root_id = 1), ist es OK, Überlappungen zwischen verschiedenen Sätzen zuzulassen. Ihre ursprüngliche Abfrage hat jedoch zwei Bäume gemischt. Um nur eine Baumstruktur wiederherzustellen, rufen Sie einfach 'rebuild_tree (1)' oder 'rebuild_tree (8)' auf. Dies wird nur die Bäume neu aufbauen, die von '1' oder' 8' beginnen. – Quassnoi

Verwandte Themen