Как найти ВСЕХ потомков, используя HierarchyID для SQL Server - PullRequest
13 голосов
/ 17 апреля 2010

Мне нужно найти всех потомков категории, используя HierarchyID для SQL Server.

Я знаю, как найти прямых детей, но я бы хотел найти детей детей, детей и так далее.

Есть ли способ сделать это, используя HierarchyID?

Ответы [ 3 ]

25 голосов
/ 18 апреля 2010

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

DECLARE @root hierarchyID;

SELECT @root = col
FROM yourTable
WHERE [whatever uniquely identifies this row]

SELECT *
FROM yourTable
WHERE col.IsDescendantOf(@root) = 1
16 голосов
/ 01 октября 2010

Для моего примера я предполагаю, что ваша таблица выглядит примерно так:

DECLARE TABLE MyTable
(
    HID hierarchyid PRIMARY KEY,
    ID int IDENTITY(1, 1),
    SomeText varchar(50)
);

Если вы хотите, чтобы все потомки узла с ID 3, опустились до максимального уровня (от корня) до 5:

DECLARE @searchNode hierarchyid;

SELECT @searchNode = HID
FROM MyTable
WHERE ID = 3;

SELECT *
FROM MyTable
WHERE HID.IsDescendantOf(@searchNode)
AND HID.GetLevel() <= 5;

Если вместо этого вам нужно 2 уровня дочерних элементов под запрошенным узлом, вам нужно будет зафиксировать уровень вашего поискового узла при первом выборе и изменить сравнение на что-то вроде

WHERE HID.IsDescendantOf(@searchNode) = 1 
AND HID.GetLevel() <= (@searchLevel + 2);
0 голосов
/ 25 марта 2014

Я фанат CTE для такого рода запросов, потому что у вас есть некоторая гибкость в том, возвращать ли только дочерние элементы, только родительский или оба, в зависимости от того, как вы структурируете свой код. В этом случае я возвращаю СОЮЗ обоих, например.

declare @MyTable table
(
    ID int not null,
    HierId hierarchyid null
);

declare @id int
set @id = 1

;with parent (TenantId, HierId, IsParent) as
(
    select
        t.ID
        ,t.HierId
        ,cast(1 as bit) as IsParent
    from @MyTable t
    where t.ID = @id
), children as
(
    select
        t.ID
        ,t.HierId
        ,cast(0 as bit) as IsParent
    from 
        @MyTable t
        inner join parent p
            on t.HierId.IsDescendantOf(p.HierId) = 1
)
select
    *
from parent
UNION
select * 
from children
...