J'avais l'habitude de lutter avec le même problème il y a 10 ans. Voici ma solution personnelle à ce problème. Mais avant de commencer à expliquer, je voudrais mentionner ses avantages et ses inconvénients.
Plus:
Vous pouvez sélectionner un sous-branches d'noeud donné dans un certain nombre de profondeurs désirées, avec le plus bas coût imaginables.
La même chose peut être faite pour sélectionner les nœuds parents.
Aucune fonctionnalité spécifique au SGBDR n'est requise. Ainsi, la même technique peut être implémentée dans l'un quelconque d'entre eux.
Tout est implémenté en utilisant un seul champ.
Moins:
Vous devriez être en mesure de définir un maximum de profondeur pour votre arbre . Vous devez également définir le nombre maximal d'enfants directs pour les nœuds.
Restructurer l'arbre est plus coûteux que de le traverser. Mais pas aussi cher que Nest Set Model. Ajout d'une nouvelle branche est la question de trouver la bonne valeur pour le champ. Et afin de déplacer une branche dans un nouveau parent, vous devez mettre à jour ce nœud et tous ses enfants (direct et indirect). La bonne nouvelle est que la suppression d'un nœud et de ses enfants est aussi simple que de le traverser (ce qui n'est absolument rien).
La technique:
Tenir compte du tableau ci-dessous comme support d'arbre:
CREATE TABLE IF NOT EXISTS `product_category` (
`product_category_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL,
`category_code` varchar(62) NOT NULL,
PRIMARY KEY (`product_category_id`),
UNIQUE KEY `uni_category_code` (`category_code`)
) DEFAULT CHARSET=utf8 ;
Toute la magie se fait dans category_code
domaine. Vous devez encoder votre adresse de branchement en une valeur de texte comme suit:
**node_name -> category_code**
Root -> 01
First child -> 01:01
Second child -> 01:02
First grandchild -> 01:01:01
First child of second child -> 01:02:01
Dans l'exemple ci-dessus, chaque nœud peut contenir jusqu'à 99 enfants directs (à supposer que nous pensons en décimal). Et puisque category_code
est de type varchar(62)
, nous pouvons avoir jusqu'à (62-2)/3 = 20 profondeur. C'est un compromis entre la profondeur que vous voulez et le nombre d'enfants directs que chaque nœud peut avoir et la taille de votre champ. Scientifiquement parlant, il s'agit d'une implémentation d'un complete tree dans lequel les branches inutilisées ne sont pas réellement créées mais réservées.
Les bonnes parties:
Maintenant, imaginez que vous voulez sélectionner des noeuds sous 01:02
. Vous pouvez le faire en utilisant une seule requête:
SELECT *
FROM product_category
WHERE
category_code LIKE '01:02:%'
Sélection des noeuds directs sous la 01:02
:
SELECT *
FROM product_category
WHERE
category_code LIKE '01:02:__'
La sélection de tous les ancêtres de 01:02
:
SELECT *
FROM product_category
WHERE
'01:02' LIKE CONCAT(category_code, ':%')
Les mauvaises parties:
Insertion d'un nouveau nœud dans l'arbre est la question de trouver le bon category_code
. Cela peut être fait en utilisant une procédure stockée ou même dans un langage de programmation comme PHP.
Étant donné que l'arbre est limité par le nombre d'enfants directs et la profondeur, une insertion peut échouer. Mais je crois que dans la plupart des cas pratiques, nous pouvons supposer une telle limitation.
Cheers.
http://en.wikipedia.org/wiki/MPTT –
Consultez la http://www.sitepoint.com/hierarchical-data-database/ pour organiser les catégories de manière hiérarchique Cela vous permettra d'éviter joint lors de l'obtention de hiérarchies. –