Question

J'ai une table MySQL qui agit comme un ensemble imbriqué afin de contenir une hiérarchie de catégories. Le schéma de la table ressemble à:

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 et rgt définissent les limites à gauche et à droite d'un noeud (la façon dont fonctionne un ensemble imbriqué est que l'identifiant de chaque nœud se situe dans les limites de son parent) et parent_id spécifie le nœud parent. L'index unique permet qu'il y ait plusieurs catégories avec le même nom, tant qu'ils ne sont pas le même parent.

Je suis en train de trouver une façon de trouver un nœud spécifique dans l'ensemble, sur la base de hiérarchie. Par exemple, si je cherche foo / bar / baz, je veux récupérer le nœud nommé baz, dont le parent est nommé bar, qui est parent est nommé foo. De toute évidence, je ne peux pas rechercher simplement par son nom, car il pourrait y avoir plusieurs catégories avec le même nom.

La façon dont je peux penser à faire est de trouver la catégorie supérieure, puis trouver chaque catégorie suivante avec le nom donné dont l'identifiant parent est celui de la catégorie précédemment trouvé, mais cela ne me semble pas très efficace. Y at-il une meilleure façon de chercher un ensemble imbriqué?

Était-ce utile?

La solution

Je ne crois pas qu'il y ait un moyen parfaitement propre et efficace de le faire avec des ensembles imbriqués. Stocker une liste des ancêtres du nœud dans une colonne dénormaliser fournirait cette efficacité, mais je ne suggère pas la mettre en œuvre.

Il existe une méthode ok'ish mais, ce qui est une requête et sera facilement atteint l'indice que vous avez déjà. Vous regardez une jointure pour chaque niveau de profondeur du nœud cible.

Pour votre exemple 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'

Il est le plus grand, mais il est probablement votre meilleur pari à moins que vous voulez aller à l'effort de stocker un tas d'informations dénormalisé. Il est assez simple pour générer le SQL en code.

Autres conseils

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.

Je l'ai vu avant dans un projet php qui m'a été remis et ugh, il est tout simplement mauvais .. si vous le pouvez, le diviser en au moins 2 tables; avoir au moins 1 pour les catégories et 1 pour les articles, afin que vous puissiez rejoindre .. De toute façon, vous allez avoir besoin de faire plusieurs requêtes Je crains

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top