2009-10-21 12 views
8

tengo su funcionamiento de la instalación conjunto de tipos de jerarquía molino anidado con las siguientes columnas:Conjuntos anidados MySQL - ¿Cómo encontrar el padre del nodo?

nombre de tabla:

myset 

columnas:

id, name, lft, rgt 

¿Alguien sabe una consulta para determinar la padre de un nodo?

He leído un par de lugares que es útil tener también una columna parent_id en su tabla para realizar un seguimiento de esto, pero parece redundante y parece que se podría perder la sincronización con el conjunto anidado si una consulta fue ejecutado incorrectamente al agregar/eliminar/mover cualquier cosa dentro del conjunto.

Respuesta

17

Mire this question. Es similar al tuyo He publicado allí una consulta que puede necesitar.

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 

Espero que haya lo que necesita.

Para la siguiente tabla:

+-------------+----------------------+-----+-----+ 
| 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 | 

se produce la salida:

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

¿Sabe por qué el 'ORDER BY t2.rgt-t1.rgt' devolverá un error en sqlite? 'SQLSTATE [HY000]: error general: 1 columna no: t1.rgt' ... funciona cuando elimino t1.rgt del pedido por lo que parece ser un problema con el orden por ... – Stoner

0

Todos los ancestros son devueltos por

SELECT id FROM thetable 
WHERE x BETWEEN lft and rgt; 

Así, la matriz directa es el antepasado con el la diferencia más pequeña entre lft y rgt.

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

si tu x debería ser la identificación del elemento, que sus declaraciones son incorrectas. – spankmaster79

2

Tuve un problema con la consulta de Lucasz. Mi versión de mysql no entendió el comando TOP. Tuve que usar LIMIT en su lugar. Aquí está el código revisado.

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 

Obviamente, cambie las cosas en [] 's según sus necesidades. También quite los [] 's. Esta consulta solo devuelve UNA fila. Al igual que ...

id parent 
7 3 
14

TOP es un comando MSSQL, limitar el uso de MySQL:

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 

debe hacer el truco ..

0

El código de spankmaster79 no estaba completamente equivocado. Modifiqué su código y funcionó.

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 

Se puede usar un máximo en lugar de la orden/de límite y es posible que tenga otra palabra clave para limitar los resultados a una fila en función de su base de datos. Entre en lugar de < y> funcionaría si su base de datos devuelve el conjunto exclusivo, lo que MySQL no hace.

3

sólo para añadir a estas respuestas, que me ha ayudado mucho,

que necesitaba para encontrar la matriz inmediata de un nodo, así como los padres nivel muy alto de una cadena de ganglios en algunos casos,

he utilizado la siguiente como una base para obtener los elementos en orden de niño a los padres

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 

es entonces una cuestión de añadir el LIMIT 1,1 sólo capturar la segunda fila que sería el padre inmediato

sino que también debe tenerse en cuenta que con la consulta anterior, si el propio nodo es el padre nivel muy alto, entonces no habría un padre inmediato, así que con la LIMIT 1,1 debe devolver un conjunto de resultados vacío

para obtener la matriz nivel muy superior i invertido el orden por cláusula, incluido un cheque si el propio nodo es el padre superior, y se limita el resultado a la primera fila

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 

en la última consulta que solía >= <= operadores por lo que el rango seleccionado abarca el nodo hijo si también le sucede ser el padre de nivel superior

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; 
Cuestiones relacionadas