2010-09-27 18 views
2

J'essaie de gérer la récupération d'un nœud dans une table nested set model, non pas via l'ID unique, mais via le nom (une chaîne), et d'autres nœuds dans l'arbre sous des parents différents peuvent être appelés de la même manière.Sélection d'un nœud dans le modèle de jeu imbriqué via un nom non unique

En ce qui concerne maintenant j'utilisé un identifiant unique pour obtenir des noeuds dans les ensembles imbriqués:

SELECT 
    node.name, node.lft, node.rgt 
FROM tbl AS parent, tbl AS node 
WHERE node.lft BETWEEN parent.lft AND parent.rgt 
AND node.id = '{$node_id}' 
GROUP BY node.id

Essayant d'étendre cette méthode à une façon plus générale pour récupérer le nœud par son nom, je suis venu avec une requête contenant autant PRESENTANT clauses que la profondeur du nœud pour récupérer, vérifier le nom de noeud et sa profondeur:

SELECT 
    node.name, node.lft, node.rgt, COUNT(node.id) AS depth 
FROM tbl AS parent, tbl AS node 
WHERE node.lft BETWEEN parent.lft AND parent.rgt 
GROUP BY node.id 
HAVING 
    (node.name = 'myParentName' AND depth = 1) 
    OR 
    (node.name = 'myParent2Name' AND depth = 2) 
    OR 
    ... 
# and so on 

Mais il est pas parfait: avoir deux nœuds avec le même nom et la même profondeur, mais au sein de différents parents, les deux sont récupérés, peu importe la hiérarchie y ils appartiennent à.

Exemple:

 
ARTICLES 
    | 
    +--PHP 
    | +--the-origins 
    | +--syntax 
    +--JS 
     +--history 
     +--syntax 

Dans ce cas, la requête ci-dessus serait de retour soit ARTICLES/PHP/syntaxe ou ARTICLES/JS/syntaxe: un noeud "syntaxe" avec la profondeur 3, en fait, est soit sous la Nœud PHP ou sous le nœud JS. Existe-t-il un moyen efficace de marcher pour résoudre ce problème?

+0

Donc, vous entrez par exemple 'PHP' et 'syntaxe' et leurs profondeurs respectives, et vous voulez que leur piste vers le haut? Ou quelle est l'entrée et la sortie exactes que vous voulez si ce n'est pas le cas? – Wrikken

+0

Oui Wrikken, j'essaie de faire exactement cela. Je prendrais la profondeur du chemin donné. –

Répondre

3

Je ne suis pas sûr de ce que vous essayez de faire ici. Essayez-vous d'accéder au nœud avec le nom de chemin ARTICLES/PHP/syntax? Si oui ce que vous devez faire serait une auto-jointure pour chaque niveau parent:

SELECT n0.* 
FROM tbl AS n0 
JOIN tbl AS n1 ON n0.lft BETWEEN n1.lft+1 AND n1.rgt 
JOIN tbl AS n2 ON n1.lft BETWEEN n2.lft+1 AND n2.rgt 
WHERE n0.name='syntax' AND n1.name='PHP' AND n2.name='ARTICLES' 

ETA re commentaires: faire-enfant direct correspond à ensemble imbriqué est pas très amusant. Vous devez essayer de sélectionner une ligne parent intermédiaire entre chaque ligne jointe. C'est la ligne que vous ne voulez pas exister, donc vous inversez alors cette condition avec une jointure nulle nulle. Par exemple:

SELECT n0.* 
FROM tbl AS n0 
JOIN tbl AS n1 ON n0.lft BETWEEN n1.lft+1 AND n1.rgt 
JOIN tbl AS n2 ON n1.lft BETWEEN n2.lft+1 AND n2.rgt 
LEFT JOIN tbl AS nn1 ON nn1.lft BETWEEN n1.lft+1 AND n0.lft-1 
LEFT JOIN tbl AS nn2 ON nn2.lft BETWEEN n2.lft+1 AND n1.lft-1 
WHERE nn1.lft IS NULL AND nn2.lft IS NULL 
AND n0.name='syntax' AND n1.name='PHP' AND n2.name='ARTICLES' 
+0

Merci bobince: cette méthode (JOINs progressive pour chaque niveau) est la même que celle utilisée dans le modèle adjacentendy, de sorte que le modèle de jeu imbriqué montre également une certaine limite dans la tâche de récupération, n'est-ce pas? –

+0

Oui, l'ensemble imbriqué ne vous apporte vraiment rien ici. L'ensemble imbriqué vous donne la possibilité de sélectionner un nombre de lignes qui satisfont certaines relations hiérarchiques; ici, vous ne voulez sélectionner qu'une seule ligne, donc il n'y a pas d'avantage. Une opération imbriquée serait idéale car, ayant fait la requête ci-dessus pour obtenir le 'lft' du nœud cible, elle aurait tous les ancêtres de ce nœud, ce qui serait' SELECT * FROM tbl WHERE (valeur lft du nœud) ENTRE lft ET rgt'. – bobince

+0

J'ai probablement mal expliqué ma tâche, mais j'ai aussi besoin d'un nœud et de toute sa hiérarchie. Bien sûr, j'utilise l'ensemble imbriqué pour tirer parti des avantages spécifiques que cette technique apporte: à travers elle, j'ai écrit des méthodes hiérarchiques appropriées pour chaque tâche, comme getParents(), getChildren(), getSiblings() et ainsi de suite. Le faire par un ID donné n'est pas un problème, puisqu'il s'agit d'un identifiant unique, mais j'aurais aimé étendre la tâche de récupération au nom. Obtenir les parents (toute la hiérarchie de l'élément demandé) est exactement ce que je voulais faire. –