Como llegar a los padres dado un hijo en SQL SERVER 2005
-
12-09-2019 - |
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.
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.