Pregunta

Tengo su configuración de tipo de jerarquía de conjunto anidado común y corriente con las siguientes columnas:

nombre de la tabla:

myset

columnas:

id, name, lft, rgt

¿Alguien conoce una consulta para determinar el padre de un nodo?

Leí un par de lugares en los que es útil tener también un Identificación de los padres en su tabla para realizar un seguimiento de esto, pero parece redundante y parece que podría desincronizarse con el conjunto anidado si una consulta se ejecutó incorrectamente al agregar/eliminar/mover algo dentro del conjunto.

¿Fue útil?

Solución

Mira a esta pregunta.Es parecido 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 necesitas.

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 |

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

Otros consejos

TOP es un comando MSSQL, use LIMIT para 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

Debería hacer el truco ..

solo para agregar a estas respuestas que me ayudaron mucho,

Necesitaba encontrar el padre inmediato de un nodo, así como el padre de nivel superior de una cadena de nodo en algunos casos,

utilicé lo siguiente como base para obtener los artículos en orden de hijo a padre

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

entonces se trata de agregar LIMIT 1,1 para capturar solo la segunda fila que sería la principal inmediata

también debe tenerse en cuenta que con la consulta anterior si el nodo en sí es el padre de nivel superior, NO tendría un padre inmediato , por lo que con el >= <= debería devolver un conjunto de resultados vacío

para obtener el padre de nivel superior, revertí el orden por cláusula, incluí una verificación si el nodo en sí mismo es el padre superior y limité 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 utilicé operadores <=> para que el rango seleccionado abarque el nodo secundario si también resulta ser el nivel superior primario

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 [] 'para satisfacer sus necesidades. También quite los [] 's. Esta consulta solo devuelve UNA fila. Me gusta así ...

id  parent
7   3
select * from myset
  where lft < :lftOfCurrent and rgt > :lftOfCurrent
  order lft desc
  limit 1

Podría usar un máximo en lugar de un orden / límite y podría necesitar otra palabra clave para limitar los resultados a una fila dependiendo de su base de datos. Entre más que & Lt; y > funcionaría si su base de datos devuelve el conjunto exclusivo, que MySQL no lo hace.

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;

Todos los ancestros son devueltos por

SELECT id FROM thetable
WHERE x BETWEEN lft and rgt;

Entonces, el padre directo es el antepasado con la menor diferencia entre lft y rgt.

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

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top