选择所有层次结构级别以及SQL Server

时间:2016-04-22 03:18:41

标签: sql sql-server stored-procedures

我正在度过这个困难时期。我已经看到了一些关于如何从给定父级的自引用表中获取所有子记录以及如何获取子记录的父级的示例。

我要做的是返回一条记录和所有给出ID的子记录。

将此置于上下文中 - 我有一个公司层次结构。其中:

#Role        Level#
--------------------
Corporate         0
Region            1
District          2
Rep               3

我需要的是一个程序,(1)确定记录的级别,(2)检索该记录和所有子记录。

作为一个地区的想法可以看到一个地区的所有地区和代表,地区可以看到他们的代表。经销商只能看到自己。

我有桌子:

ID            ParentId           Name
-------------------------------------------------------
1             Null               Corporate HQ
2             1                  South Region
3             1                  North Region
4             1                  East Region
5             1                  West Region
6             3                  Chicago District
7             3                  Milwaukee District
8             3                  Minneapolis District
9             6                  Gold Coast Dealer
10            6                  Blue Island Dealer

我该怎么做:

CREATE PROCEDURE GetPositions
    @id int
AS
BEGIN
    --What is the most efficient way to do this--
END
GO

例如@id = 3的预期结果,我想返回:

3, 6, 7, 8, 9, 10

我很感激任何帮助或想法。

2 个答案:

答案 0 :(得分:6)

你可以通过递归CTE来做到这一点:

DECLARE @id INT = 3;

WITH rCTE AS(
    SELECT *, 0 AS Level FROM tbl WHERE Id = @id
    UNION ALL
    SELECT t.*, r.Level + 1 AS Level
    FROM tbl t
    INNER JOIN rCTE r
        ON t.ParentId = r.ID
)
SELECT * FROM rCTE OPTION(MAXRECURSION 0);

ONLINE DEMO

答案 1 :(得分:0)

假设您使用的是相当现代的SQL Server版本,您可以使用hierarchyid数据类型和一点点肘部油脂。首先,设置:

alter table [dbo].[yourTable] add [path] hierarchyid null;

接下来,我们将填充新列:

with cte as (
   select *, cast(concat('/', ID, '/') as varchar(max)) as [path]
   from [dbo].[yourTable]
   where [ParentID] is null

   union all

   select child.*, 
      cast(concat(parent.path, child.ID, '/') as varchar(max)) as [path]
   from [dbo].[yourTable] as child
   join cte as parent
      on child.ParentID = parent.ID
)
update t
set path = c.path
from [dbo].[yourTable] as t
join cte as c
   on t.ID = c.ID;

这只是一个标准的标准递归表表达式,其中一个计算列表示层次结构。那是困难的部分。现在,您的程序可能如下所示:

create procedure dbo.GetPositions ( @id int ) as
begin
   declare @h hierarchyid
   set @h = (select Path from [dbo].[yourTable] where ID = @id);

   select ID, ParentID, Name
   from [dbo].[yourTable]
   where Path.IsDescendentOf(@h) = 1;
end

因此,总结一下,您对hierarchyid所做的一切就是存储给定行的沿袭,这样您就不必在选定的时间即时计算它。