2009-10-21 9 views
8

je votre course de l'ensemble configuration de type hiérarchie imbriquée moulin avec les colonnes suivantes:Ensembles imbriqués MySQL - Comment trouver le parent du noeud?

Nom de la table:

myset 

colonnes:

id, name, lft, rgt 

Quelqu'un sait-il une requête pour déterminer la parent d'un noeud?

J'ai lu quelques endroits qu'il est pratique d'avoir aussi un parent_id colonne de votre table pour garder une trace de cela, mais il semble redondant et il semble que cela pourrait sortir de la synchronisation avec l'ensemble imbriqué si une requête a été exécuté de manière incorrecte lors de l'ajout, de la suppression ou du déplacement de quelque chose dans l'ensemble.

Répondre

17

Regardez this question. C'est semblable au tien. J'ai posté une requête dont vous pourriez avoir besoin.

SELECT title, (SELECT TOP 1 title 
      FROM tree t2 
      WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt  
      ORDER BY t2.rgt-t1.rgt ASC) AS parent 
FROM tree t1 
ORDER BY rgt-lft DESC 

J'espère que vous avez ce dont vous avez besoin.

Pour le tableau suivant:

+-------------+----------------------+-----+-----+ 
| category_id | name     | lft | rgt | 
+-------------+----------------------+-----+-----+ 
|   1 | ELECTRONICS   | 1 | 20 | 
|   2 | TELEVISIONS   | 2 | 9 | 
|   3 | TUBE     | 3 | 4 | 
|   4 | LCD     | 5 | 6 | 
|   5 | PLASMA    | 7 | 8 | 
|   6 | PORTABLE ELECTRONICS | 10 | 19 | 
|   7 | MP3 PLAYERS   | 11 | 14 | 
|   8 | FLASH    | 12 | 13 | 
|   9 | CD PLAYERS   | 15 | 16 | 
|   10 | 2 WAY RADIOS   | 17 | 18 | 

il produit la sortie:

title    | parent 
---------------------------------------------- 
ELECTRONICS   | NULL 
PORTABLE ELECTRONICS | ELECTRONICS 
TELEVISIONS   | ELECTRONICS 
MP3 PLAYERS   | PORTABLE ELECTRONICS 
FLASH    | MP3 PLAYERS 
CD PLAYERS   | PORTABLE ELECTRONICS 
2 WAY RADIOS   | PORTABLE ELECTRONICS 
TUBE     | TELEVISIONS 
LCD     | TELEVISIONS 
PLASMA    | TELEVISIONS 
+0

Savez-vous pourquoi 'ORDER BY t2.rgt-t1.rgt' retournera une erreur dans sqlite? 'SQLSTATE [HY000]: Erreur générale: 1 pas une telle colonne: t1.rgt' ... cela fonctionne quand je supprime t1.rgt de l'ordre par donc il semble être un problème avec ordre par ... – Stoner

0

Tous les ancêtres sont retournés par

SELECT id FROM thetable 
WHERE x BETWEEN lft and rgt; 

Ainsi, le parent direct est l'ancêtre de la la plus petite différence entre lft et rgt.

SELECT id FROM thetable 
WHERE x BETWEEN lft and rgt 
ORDER BY (rgt-lft) 
LIMIT 1 
+1

si votre x devrait soyez l'identifiant de l'élément, alors que vos affirmations sont fausses. – spankmaster79

2

J'ai eu un problème avec la requête de Lucasz. Ma version de mysql ne comprenait pas la commande TOP. J'ai dû utiliser LIMIT à la place. Voici le code révisé.

SELECT 
    `id`, 
    (SELECT 
     `id` 
    FROM 
     `[*** YOUR TABLE ***]` AS `t2` 
    WHERE 
     `t2`.`left_id` < `t1`.`left_id`AND 
     `t2`.`right_id` > `t1`.`right_id` 
    ORDER BY 
     `t2`.`right_id`-`t1`.`right_id`ASC 
    LIMIT 
     1) AS `parent` 
FROM 
    `[*** YOUR TABLE ***]` AS `t1` 
WHERE 
    `t1`.`id` = [*** ID OF THE NODE WHOS PARENT YOU WISH TO LOOKUP ***] 
ORDER BY 
    `right_id`-`left_id` DESC 

De toute évidence, changer les choses dans le [] 's en fonction de vos besoins. Retirez également les []. Cette requête ne renvoie qu'une seule ligne. Comme si ...

id parent 
7 3 
14

TOP est une commande MSSQL, MySQL pour une utilisation LIMIT:

SELECT title, (SELECT title 
     FROM tree t2 
     WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt  
     ORDER BY t2.rgt-t1.rgt ASC 
     LIMIT 1) 
AS parent FROM tree t1 
ORDER BY (rgt-lft) DESC 

devrait faire l'affaire ..

0

Le code de spankmaster79 n'a pas été complètement faux. J'ai modifié son code et cela a fonctionné.

SELECT parent . * FROM Nested_Category AS node, Nested_Category AS parent 
enter code hereWHERE node.leftSide 
BETWEEN parent.leftSide 
AND parent.rightSide 
AND node.id ='Enter the Node ID' 
ORDER BY (
parent.rightSide - parent.leftSide 
) 
LIMIT 1 , 1 
0
select * from myset 
    where lft < :lftOfCurrent and rgt > :lftOfCurrent 
    order lft desc 
    limit 1 

Vous pouvez utiliser un maximum plutôt que de l'ordre/limite et vous pourriez avoir besoin un autre mot-clé pour limiter les résultats à une ligne en fonction de votre base de données. Entre plutôt que < et> fonctionnerait si votre base de données renvoyait l'ensemble exclusif, ce qui n'est pas le cas de MySQL.

3

juste ajouter à ces réponses qui m'a beaucoup aidé,

i nécessaires pour trouver le parent immédiat d'un nœud, ainsi que le parent de niveau très haut d'une chaîne de noeud dans certains cas,

i utilisé ce qui suit comme une base pour obtenir les éléments pour enfant à parent

SELECT parent.* FROM 
     nested_set node, 
     nested_set parent 
     WHERE (
      node.set_left BETWEEN parent.set_left AND parent.set_right   
     ) 
     AND node.set_id={CHILD_NODE_ID_HERE} 
     ORDER BY parent.set_right - parent.set_left 
     #LIMIT 1,1 

il est alors une question d'ajouter le LIMIT 1,1 seulement capturer la deuxième ligne qui serait le parent immédiat

il convient également de noter que la requête ci-dessus si le nœud lui-même est le parent de niveau très haut, il n'y aurait pas d'parent immédiat, donc avec l'LIMIT 1,1 il doit retourner un jeu de résultats vide

pour obtenir le parent de niveau très haut i inversé l'ordre par article, inclus un chèque si le nœud lui-même est le parent supérieur, et limité le résultat à la première ligne

SELECT parent.* AS top_level_right FROM 
     nested_set node, 
     nested_set parent 
     WHERE (
      node.set_left >= parent.set_left 
      AND node.set_left <= parent.set_right 
     ) 
     AND node.set_id={CHILD_NODE_ID_HERE} 
     ORDER BY parent.set_left - parent.set_right 
     LIMIT 1 

dans la dernière requête i utilisé >= <= opérateurs afin que la plage sélectionnée englobe le noeud enfant s'il arrive aussi à être le parent de premier niveau

1
SELECT parent.name 
FROM myset AS node, myset AS parent 
WHERE parent.lft < node.lft 
AND parent.rgt > node.rgt 
AND node.id = {YOUR CATEGORY ID} 
ORDER BY (parent.rgt - parent.lft) ASC LIMIT 1; 
Questions connexes