2009-08-16 16 views
1

Ich habe eine MySQL-Tabelle, die wie eine verschachtelte Menge wirkt, um eine Hierarchie von Kategorien zu enthalten. Das Tabellenschema wie folgt aussieht:Durchsuchen einer verschachtelten Menge

CREATE TABLE IF NOT EXISTS `categories` (
    `id` int(11) NOT NULL auto_increment, 
    `name` varchar(200) NOT NULL, 
    `parent_id` int(11) default NULL, 
    `lft` int(11) default NULL, 
    `rgt` int(11) default NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `index_categories_on_parent_id_and_name` (`parent_id`,`name`) 
) 

lft und rgt die linken und rechten Grenzen eines Knotens (die Art und Weise ein verschachtelter Satz funktioniert, ist, dass jeder ID des Knotens innerhalb seiner elterlichen Grenzen fällt) definieren, und parent_id gibt den übergeordneten Knoten . Der eindeutige Index ermöglicht mehrere Kategorien mit demselben Namen, sofern sie nicht denselben übergeordneten Namen haben.

Ich versuche, einen richtigen Weg zu finden, einen bestimmten Knoten in der Menge zu finden, basierend auf Hierarchie. Wenn ich beispielsweise nach foo/bar/baz suche, möchte ich den Knoten namens baz abrufen, dessen Elternteil den Namen bar trägt und dessen Elternteil foo heißt. Natürlich kann ich nicht nur nach Namen suchen, da es mehrere Kategorien mit demselben Namen geben könnte. Die Art, wie ich das tun kann, ist, die oberste Kategorie zu finden und dann jede nachfolgende Kategorie mit dem gegebenen Namen zu finden, deren Eltern-ID die der vorher gefundenen Kategorie ist, aber das scheint mir nicht sehr effizient zu sein. Gibt es eine bessere Möglichkeit, ein verschachteltes Set zu durchsuchen?

Antwort

1

Ich glaube nicht, dass es eine perfekt saubere und effiziente Möglichkeit ist mach das mit verschachtelten Sets. Das Speichern einer Liste der Vorfahren des Knotens in einer denormalisierten Spalte würde dies effizient bereitstellen, aber ich empfehle nicht, sie zu implementieren.

Es gibt jedoch eine ok'ish Methode, die 1 Abfrage ist und bequem den Index, den Sie bereits haben, treffen wird. Sie betrachten einen Join für jede Tiefebene des Zielknotens.

Für Ihr Beispiel foo-bar-baz

select c3.*
from categories c1
inner join categories c2 on c2.parent_id = c1.id AND c2.name = 'bar'
inner join categories c3 on c3.parent_id = c2.id AND c2.name = 'baz'
where c1.name = 'foo'

Es ist nicht die beste, aber es ist wahrscheinlich die beste Wahl, wenn Sie eine Reihe von denormalisierter Informationen zu speichern, um den Aufwand zu gehen. Es ist ziemlich einfach, SQL im Code zu generieren.

0

Ich habe das schon mal in einem PHP-Projekt gesehen, das mir ausgehändigt wurde, und hm, es ist einfach nur schlecht. wenn du kannst, brich es in mindestens 2 Tabellen; haben Sie mindestens 1 für Kategorien und 1 für Artikel, so können Sie beitreten .. entweder müssen Sie mehrere Abfragen zu tun, ich habe Angst

+0

Ich glaube nicht, dass Sie die Frage ganz verstanden haben; Ich habe separate Tabellen für Kategorien und Gegenstände, aber ich bin nicht besorgt über Gegenstände hier. Ich möchte nur die ID einer bestimmten Kategorie basierend auf einer bestimmten Hierarchie erhalten. –

1
TopVar = 'foo' 
MidVar = 'bar' 
BotVar = 'baz' 

SELECT D0.* 
FROM categories D0, categories D1, categories D2 
WHERE D0.name = :BotVar 
    AND D0.lft > D1.lft 
    AND D0.rgt < D1.rgt 
    AND D1.name = :MidVar 
    AND D1.lft > D2.lft 
    AND D1.rgt < D2.rgt 
    AND D2.name = :TopVar; 

-Al.

+0

Kleiner Tipp, der mir zu lange gedauert hat, um mit verschachtelten Sets zu arbeiten. Um Nachfahren eines Knotens zu finden, beziehen Sie sich nur auf die Spalte 'lft' in Ihrer Abfrage. Wenn Sie auf die linke und rechte Spalte klicken, enthält Ihre Abfrage zwei Bereichsbedingungen (das ist etwas optimierungsresistent). Wenn Sie sich nur auf die linke Seite beziehen, handelt es sich um eine einzelne Bereichsbedingung, die vollständig durch einen Index für lft abgedeckt werden kann. Nehmen wir an, wir wollen die Nachkommen von Knoten A, der 12 und rechts 155: select * from categories c where c.lft between 12 and 155 verlassen hat – Michael

Verwandte Themen