Нужна помощь с рекурсией в SQL Server 2005 - PullRequest
2 голосов
/ 03 августа 2009

Я представляю дерево в таблице, и мне нужно иметь возможность получить корневой узел (TOP ID) определенного элемента. Корневой узел всегда имеет ParentID из null. Например, если таблица выглядит так:

ID   ParentID
1   null
2   null
3   null
4   2
5   1
6   2
7   6
8   4
9   8
10  6

Когда ID=10, TOP ID = 2; когда ID=9, то TOP ID = 3; и так далее. Можно ли написать функцию сервера SQL, которая возвращает TOP ID, если дано ID?

Ответы [ 6 ]

3 голосов
/ 03 августа 2009

Вот рекурсивный пример от sproc, который у меня есть, который найдет Parent (родительский ID = null) для любого данного идентификатора - (@ID), данного sproc. Это то, что вы ищете?

    WITH recurseUp (ID, ParentID)
    AS
    (
        SELECT ID, ParentID
        FROM myTable
        WHERE ID = @ID 
        UNION ALL
        SELECT b.ID, b.ParentID
        FROM recurseUp a JOIN myTable b 
        ON (a.ParentID = b.ID)
    )
SELECT ID FROM recurseUP WHERE ParentID is null
2 голосов
/ 03 августа 2009

MSDN имеет довольно хороший набор примеров использования Общих табличных выражений для написания рекурсивных запросов. Задним делом было очень тяжело делать это до SQL Server 2005 (прямо сейчас решая эту проблему в старом приложении Server 2000).

1 голос
/ 03 августа 2009

Рекурсия в SQL до SQL 2003 (то есть в SQL Server 2000) выглядит несколько уродливо; для каждого уровня в вашем дереве вам нужно написать отдельный оператор соединения обратно в исходную таблицу. При условии, что количество уровней в вашей иерархии фиксировано, вы можете написать что-то вроде этого.

create table #Hell (
parent int,
id int,
name varchar(30)
)

insert into #Hell values (NULL, 1, 'The Boss')
insert into #Hell values (1, 2, 'The Boss'' PA')
insert into #Hell values (1, 3, 'Production Director')
insert into #Hell values (3, 4, 'Jim''l Fixit')


select * from #Hell H1
inner join #Hell H2
ON H1.id=H2.parent
inner join #Hell H3
ON H2.id=H3.parent
WHERE H3.Id=4  --Find the boss for Jim

drop table #Hell

К счастью, SQL Server 2005 имеет с общим табличным выражением, которое позволяет довольно легко писать рекурсивные операции. Смотри Смотри http://www.4guysfromrolla.com/webtech/071906-1.shtml

Вам также следует знать о различных способах представления деревьев в базе данных. Посмотрите слайды на деревьях в SQL из этой презентации http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back

0 голосов
/ 03 августа 2009
WITH    q AS
        (
        SELECT  id, parentID
        FROM    mytable
        WHERE   id = 10
        UNION ALL
        SELECT  mytable.id, mytable.parentid
        FROM    q
        JOIN    mytable
        ON      mytable.parentId = q.id
        )
SELECT  *
FROM    q
WHERE   parentID IS NULL
0 голосов
/ 03 августа 2009

Это возможно, но единственный известный мне метод - использовать CURSOR и рекурсивную хранимую процедуру. Это действительно плохой способ сделать что-то с точки зрения производительности (обычно). Если возможно, вы можете рассмотреть стоимость наличия дополнительного корневого родительского узла, который вы будете обновлять с помощью кода по мере продвижения вперед.

0 голосов
/ 03 августа 2009

MSDN до этой статьи , которая, скорее всего, объяснит это лучше, чем вы, вероятно, получите в формате, который нам разрешен на этом сайте.

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