Pregunta

Tengo una tabla como la siguiente

childid      parentid
------------------------
1       0
2       1
3       2
4       2
5       3
6       4
7       0
8       7
9       8
10      1

Si doy un childid como 5, la parentid será 1 (salida)

Si doy un childid como 9, la parentid será 7. (salida)

es decir. parentid la raíz es 0 y la consulta debe detenerse ahí.

¿Cómo resolver una consulta tal?

Por favor, ayuda.

¿Fue útil?

Solución

Creo que debería cambiar el nombre de child_id a nodo, su parent_id a child_of. Su denominación columna se confunde un poco

create table stack_overflow
(
node int, child_of int
);


insert into stack_overflow(node, child_of) values
(1,0),
(2,1),
(3,2),
(4,2),
(5,3),
(6,4),
(7,0),
(8,7),
(9,8),
(10,1);

Esto funciona en cualquier RDBMS CTE con capacidad

with find_parent(parent, child_of, recentness) as
(
    select node, child_of, 0 
    from stack_overflow
    where node = 9
    union all
    select i.node, i.child_of, fp.recentness + 1
    from stack_overflow i
    join find_parent fp on i.node = fp.child_of
)
select top 1 parent from find_parent 
order by recentness desc

Salida:

parent
7

[EDIT: más flexible y futura de agua]

with find_parent(node_group, parent, child_of, recentness) as
(
    select node, node, child_of, 0
    from stack_overflow
    where node in (5,9)
    union all
    select fp.node_group, i.node, i.child_of, fp.recentness + 1
    from stack_overflow i
    join find_parent fp on i.node = fp.child_of
)
select q.node_group as to_find, parent as found 
from find_parent q 
join
(
    select node_group, max(recentness) as answer
    from find_parent
    group by node_group 
) as ans on q.node_group = ans.node_group and q.recentness = ans.answer 
order by to_find    

Salida:

to_find     found
5           1
9           7

Si está utilizando PostgreSQL , el código anterior podría reducirse a:

with recursive find_parent(node_group, parent, child_of, recentness) as
(
    select node, node, child_of, 0
    from stack_overflow
    where node in (5,9)
    union all
    select fp.node_group, i.node, i.child_of, fp.recentness + 1
    from stack_overflow i
    join find_parent fp on i.node = fp.child_of
)
select distinct on (node_group) node_group as to_find, parent as found 
from find_parent 
order by to_find, recentness desc

DISTINCT en las rocas! : -)

Otros consejos

Si lo que quieres es la ParentID raíz, puede utilizar esta función recursiva:

CREATE FUNCTION test_func
(
    @ParentID int
)
RETURNS int
AS
BEGIN
    DECLARE @result int;
    DECLARE @childID int;

    SET @childID = (SELECT ChildID FROM YourTable WHERE ParentID = @ParentID)

    IF (@childID = 0)
        SET @result = @ParentID
    ELSE
        SET @result = dbo.test_func(@childID)

    RETURN @result    
END
GO

A continuación, en la consulta principal:

SELECT dbo.test_func(5)

El paso de 5 retorna 1, 9 devuelve 7 sobre la base de los datos proporcionados. Si necesita cada ParentID que es hasta esa cadena, probablemente debería utilizar un CTE.

Creo desea una consulta recursiva, se debe utilizar expresiones de tabla comunes. Te daré un enlace con un ejemplo muy similar que el que usted está utilizando.

aquí es el solución. Me ayudó hace unos meses.

Un simple ejemplo de obtener el ID de padres concuerda con el ID determinado niño es:

select parentid 
from MyTable 
where childid = 5

Sin embargo, para los datos anteriores, esto va a devolver ningún registro.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top