Как получить родительский объект в SQL SERVER 2005 - PullRequest
3 голосов
/ 09 июля 2009

У меня есть такая таблица

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, и запрос должен на этом остановиться.

Как решить такой запрос?

Пожалуйста, помогите.

Ответы [ 4 ]

5 голосов
/ 10 июля 2009

Я думаю, что вы должны переименовать ваш child_id в node, ваш parent_id в child_of. Название вашей колонки немного сбивает с толку

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 :

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

Если вы используете Postgres , приведенный выше код может быть сокращен до:

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

ОТЛИЧАЕТСЯ НА КАМЕНЬ! : -)

4 голосов
/ 09 июля 2009

Если ВСЕ, что вы хотите, является корневым ParentID, вы можете использовать эту рекурсивную функцию:

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 на основе предоставленных вами данных. Если вам нужен каждый ParentID, входящий в эту цепочку, вам, вероятно, следует использовать CTE.

0 голосов
/ 09 июля 2009

Простой пример получения родительского идентификатора, совпадающего с заданным дочерним идентификатором:

select parentid 
from MyTable 
where childid = 5

Однако для приведенных выше данных это не вернет никаких записей.

0 голосов
/ 09 июля 2009

Я думаю, что вы хотите рекурсивный запрос, вы должны использовать Common Table Expressions. Я дам вам ссылку с примером, очень похожим на тот, который вы используете.

Я думаю здесь - это решение. Это помогло мне несколько месяцев назад.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...