l'ordre sql hiérarchie de l'arbre de
Quelle est la meilleure façon de trier un tableau comme ceci:
CREATE TABLE category(
id INT(10),
parent_id INT(10),
name VARCHAR(50)
);
INSERT INTO category (id, parent_id, name) VALUES
(1, 0, 'pizza'), --node 1
(2, 0, 'burger'), --node 2
(3, 0, 'coffee'), --node 3
(4, 1, 'piperoni'), --node 1.1
(5, 1, 'cheese'), --node 1.2
(6, 1, 'vegetariana'), --node 1.3
(7, 5, 'extra cheese'); --node 1.2.1
De faire le tri de façon hiérarchique par id ou nom:
"pizza" //node 1
'piperoni' //node 1.1
"fromage" //node 1.2
"extra fromage" //node 1.2.1
'vegetariana' //node 1.3
'burger' //node 2
'café' //node 3
EDIT: le numéro à la fin de la nom est de visualiser la structure de mieux, ce n'est pas pour le tri.
EDIT 2: comme mentionné à plusieurs reprises ... le nombre à la fin de la name
"fromage 1.2" était uniquement pour la visualisation but, PAS pour le tri. J'ai déménagé comme des commentaires, trop de gens n'ai pas compris, désolé.
- Oracle a une façon de le faire avec
START WITH parent_id = 0 CONNECT BY PRIOR id = parent_id ORDER SIBLINGS BY id ASC
. Je pense que MySQL n'ont pas de telles requêtes hiérarchiques. - en fait presque tous les SGBD à l'exception de quelques (y compris MySQL) peut faire quelque chose comme ça à l'aide d'une expression de table commune récursive.
- est le tableau de la structure déjà défini ou vous êtes dans la phase de planification et pourrait choisir une autre structure? combien de candidatures avez-vous un plan du tableau ? est-il modifié souvent ou est-il important d'avoir de nombreux accès en lecture à ce sujet ?
- plus de colonnes peuvent être ajoutées (top_parent_id, depth_level ..) mais je suis à la recherche de solution dans cette structure si possible. La profondeur peut être ajouté (l'arbre n'est pas limitée à 3 niveaux), mais en général, il ne devrait pas être plus de 50 à 100 entrées et de vitesse pour cette requête n'est pas un problème.
- Voir la Gestion Hiérarchique des Données dans MySQL pour un certain nombre de recettes.
- Vous feriez bien de revoir DONC, la question que j'ai écrit sur ce sujet: stackoverflow.com/questions/4048151/...
Vous devez vous connecter pour publier un commentaire.
Par l'ajout d'une colonne chemin d'accès et un déclencheur, ce qui peut être fait assez facilement.
D'abord ajouter une colonne de type varchar qui contiendra le chemin de la racine au nœud:
Puis ajouter un déclencheur qui calcule le chemin d'accès lors de l'insertion:
(simplement concats la nouvelle carte d'identité avec chemin d'accès du parent)
Puis il suffit de sélectionner la commande par le chemin d'accès:
Résultat:
Voir violon.
De cette façon, les coûts de maintenance est également minime. Le champ chemin d'accès est caché lors de l'insertion et est calculée à l'aide d'un déclencheur. La suppression d'un nœud a pas de frais généraux, puisque tous les enfants du nœud sont également supprimés. Le seul problème, c'est quand la mise à jour de la parent_id d'un nœud; eh Bien, ne le faites pas! 🙂
Imbriquée Arbre Ensembles en combinaison avec un
level
colonne est vraiment une bonne technique pour la lecture et le tri de l'arbre en fonction des structures. Il est facile de sélectionner un sous-arbre, limiter le nombre de résultats à un certain niveau, et faire le tri dans une requête. Mais le coût pour l'insertion et suppression d'entrées est relativement haute, de sorte que vous devriez utiliser si vous interrogez vos données le plus souvent à vous écrire et où le rendement en lecture est importante. (pour 50 à 100 le moment de suppression, d'insertion ou de déplacer des éléments devrait pas être un problème, même avec 1000 il ne devrait pas être problématique).Avec chaque entrée, vous magasin il est
level
et de la valeur pourleft
etright
, dans l'exemple ci-dessous: (left
,right
,level
) si vous souhaitez ne sélectionner que les1.2
avec ses descendants vous feriez:si vous souhaitez sélectionner uniquement les enfants ont ensuite
si vous voulez de sorte que vous pourriez faire
Tri par d'autres domaines, tout en gardant le groupement de la hiérarchie pourrait être problématique, selon la façon dont vous souhaitez trier.
Fermeture de la Table (pour l'achèvement, mais je ne recommande pas pour votre cas d'utilisation). Il stocke tous les chemins dans l'arbre et, par conséquent, l'espace de stockage requis pour la hiérarchie va se développer très rapidement si vous avez de nombreux niveaux.
Chemin Énumération vous y stocker le chemin d'accès de chaque élément avec l'entrée
/0/
,/0/1/
interrogation chemin d'accès est facile là, mais pour le tri, il n'est pas flexible.Pour une petite quantité de participations je voudrais utiliser Imbriquée Arbre Ensembles.
malheureusement je n'ai pas une bonne page de référence qui décrit ces techniques et les compare.
si il n'y a que 3 niveaux d'imbrication vous pouvez faire quelque chose comme ça
si vous disposez de plusieurs niveaux d'imbrication il serait plus difficile
pour plus de nidification niveau, vous pouvez écrire la fonction
j'ai donc maintenant sur
j'ai
c2.name
la commande ne fonctionne pasSELECT c1.name FROM category as c1 LEFT JOIN category as c2 ON c1.parent_id = c2.id OR (c1.parent_id = 0 AND c1.id = c2.id) ORDER BY c2.id, c1.id;
et je peux voir seulement 2 niveaux (supplément de fromage refernce à pizza(1), pas de fromage(5))(7, 5, 'extra cheese 1.2.1');
Je pense que tout le monde est sur-architecte-tion de la solution. Si votre but est vraiment de vous faire représenter par votre exemple, comme le 3-niveaux avec le virtuel de niveau supérieur de 0 id, cela devrait suffire.
Une façon est d'avoir séparé la chaîne de champ pour le stockage de l'intégrale de chemin de n'importe quel nœud.
Vous avez besoin pour maintenir ce domaine sur tous les insert/update/delete.
Vous pouvez avoir valeur de champ comme ci-dessous
Vous avez besoin de commander par le champ chemin d'accès à des arbres dans le bon ordre de tri.
Voir SqlFiddle Démo
De cette façon, vous n'avez pas besoin de récursivité dans le langage de programmation pour imprimer la totalité de l'arbre dans l'ordre de tri correct.
Note:
Cet exemple ne fonctionnera que si vous avez max ID jusqu'à 9, comme|1||11| viendra plus tôt que|1||2|
Pour résoudre ce problème, vous devez faire rembourrage pour la construction chaîne basée sur le maximum de la valeur du champ ID est prévu pour votre application, comme l'exemple ci-dessous avec la valeur maximum prévu est de 999 (3 chiffres)
|001||002|
Selon mon expérience, cette solution ne devrait être bon pour la poignée de l'arbre avec la profondeur jusqu'à 7-8 niveau.
Pour une Autre méthode : Cliquez Ici
order
domaine ou quelque chose comme ça. Thenks pour l'article, il est facile à faire avec récursive code de trop, je suis à la recherche pour SQL variante de cette structure de base.Sql
MySql
Essayer
ORDER BY name , id
à la fin de votre requête SQL.Cela permettra de trier par nom et d'utiliser l'id de régler tous les liens.