문제

이와 같은 테이블이 있습니다

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

내가 childid를 5로 주면, 부모는 1 (출력)이됩니다.

내가 childid를 9로 주면, 부모는 7이됩니다.

즉, 루트 부모는 0이고 쿼리가 중지되어야합니다.

그러한 쿼리를 해결하는 방법?

도와주세요.

도움이 되었습니까?

해결책

나는 당신이 당신의 child_id를 노드로 바꿔야한다고 생각합니다. 열 이름 지정은 약간 혼란 스럽습니다

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);

이것은 모든 CTE 가능 RDBM에서 작동합니다:

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

산출:

parent
7

편집 : 더 유연하고 미래 방지:

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    

산출:

to_find     found
5           1
9           7

사용하는 경우 포스트 그레, 위의 코드는 다음과 같이 단축 될 수 있습니다.

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

바위에 뚜렷한! :-)

다른 팁

당신이 원하는 것이 루트 부모라면이 재귀 기능을 사용할 수 있습니다.

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

그런 다음 기본 쿼리에서 :

SELECT dbo.test_func(5)

5 개의 반품 1, 9는 제공된 데이터를 기준으로 7을 반환합니다. 그 체인에있는 모든 부모가 필요한 경우 CTE를 사용해야합니다.

재귀 쿼리를 원한다고 생각합니다. 일반적인 테이블 표현식을 사용해야합니다. 나는 당신이 사용하는 것과 매우 유사한 예와 링크를 제공 할 것입니다.

제 생각에는 여기 해결책입니다. 몇 달 전에 나에게 도움이되었습니다.

주어진 자식 신분증과 일치하는 부모 ID를 얻는 간단한 예는 다음과 같습니다.

select parentid 
from MyTable 
where childid = 5

그러나 위의 데이터의 경우 레코드를 반환하지 않습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top