Frage

Ich habe eine MySQL-Tabelle bekommt, die wie ein verschachtelter Satz, um eine Hierarchie von Kategorien zu enthalten wirkt. Das Tabellenschema wie folgt aussieht:

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 rgt und die linken und rechten Grenzen eines Knotens definieren (die Art und Weise ein verschachtelter Satz funktioniert, ist, dass jeder ID des Knotens innerhalb seiner elterlichen Grenzen fällt) und parent_id gibt den übergeordneten Knoten. Der eindeutige Index ermöglicht es mehrere Kategorien mit dem gleichen Namen zu sein, solange sie die gleichen Eltern nicht haben.

Ich versuche, eine richtige Art und Weise, um herauszufinden, einen bestimmten Knoten in der Menge zu finden, basierend auf Hierarchie. Zum Beispiel, wenn ich für foo / bar / baz aussehen, möchte ich den Knoten mit dem Namen baz abzurufen, dessen Mutter heißt bar, die Eltern heißt foo. Natürlich, ich kann nicht einfach nach dem Namen suchen, denn es gibt mehrere Kategorien mit dem gleichen Namen sein könnte.

So wie ich denken kann, dies zu tun, ist die oberste Kategorie zu finden, finden Sie dann jede nachfolgende Kategorie mit dem angegebenen Namen, deren Mutter-ID ist, dass die zuvor gefundene Kategorie, aber dies scheint nicht sehr effizient zu mir. Gibt es einen besseren Weg, um einen verschachtelten Satz suchen?

War es hilfreich?

Lösung

Ich glaube nicht, gibt es eine perfekt saubere und effiziente Möglichkeit, dies mit verschachtelten Sätzen zu tun. effizient würde dies in einer denormalized Spalte eine Liste der Vorfahren des Knotens zu speichern, aber ich schlage vor, es nicht zu implementieren.

Es gibt eine ok'ish Methode aber, die 1 Abfrage und wird getroffen bequem den Index, den Sie bereits haben. Sie suchen in einem für jede Ebene der Tiefe des Zielknotens verbinden.

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 zu den Bemühungen gehen wollen eine Reihe von denormalisierter Informationen zu speichern. Es ist ziemlich einfach, wie auch die SQL-in-Code zu generieren.

Andere Tipps

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.

Ich habe diese zuvor in einem PHP-Projekt gesehen, die mir übergeben wurde, und puh, es ist nur schlecht .. wenn Sie können, brechen sie in mindestens zwei Tabellen; zumindest 1 für Kategorien und 1 für die Einzelteile, so können Sie kommen .. Wie auch immer Sie brauchen werden mehrere Abfragen zu tun, fürchte mich

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top