使用SQL

时间:2017-02-14 01:14:37

标签: sql sql-server

根据下面的系列记录,如何获得最后一个子记录(ST)给出其位置层次结构的事实。

图例

PM (Project Manager) - is the highest role position
PS (Project Supervisor) - is the down-line of PM
ST (Staff) - is the down-line of PS and the lowest role position 

数据

ID   Name           RoleCode    RoleDescription       ReportingtoID 
1    Will Smith       PM        Project Manager        NULL
2    Zoey Nathan      PM        Project Manager        NULL
3    Louise Norton    PS        Project Supervisor     1
4    Cynthia Villaz   PS        Project Supervisor     1
5    Ronald Trimp     PS        Project Supervisor     2
6    Lebron James     ST        Staff                  3
7    Raymond Trimp    ST        Staff                  4
8    Kevin Garn       ST        Staff                  3
9    Kobe Spars       ST        Staff                  5
10   Paul Lee         ST        Staff                  3
11   Mark Pingris     ST        Staff                  4
12   Elton Horn       ST        Staff                  1
13   Shayne Wyn       ST        Staff                  1

示例1

如果我们要获取 Zoey Nathan(PM)的下线,由于此人没有下线,所以不会反映任何记录。

如果我们要取 Will Smith(PM)的子根,结果应该低于:

以下说明:威尔史密斯有两个下线即路易斯诺顿辛西娅维拉兹,他们两个也有所不同下线,这都是STAFF的位置。由于STAFF是最低层次,因此应显示所有这些层次结构。此外,还有一个实例,即STAFF也直接向项目经理报告,这就是为什么 Elton Horn Shayne Wyn 都会对结果产生影响。

渴望输出

ID   Name           RoleCode    RoleDescription       ReportingtoID 
6    Lebron James     ST        Staff                  3
7    Raymond Trimp    ST        Staff                  4
8    Kevin Garn       ST        Staff                  3
10   Paul Lee         ST        Staff                  3
11   Mark Pingris     ST        Staff                  4
12   Elton Horn       ST        Staff                  1
13   Shayne Wyn       ST        Staff                  1

示例2

如果我们要取 Cynthia Villaz(PS)的子根,结果应该如下:

渴望输出

ID   Name           RoleCode    RoleDescription       ReportingtoID 
7    Raymond Trimp    ST        Staff                  4
11   Mark Pingris     ST        Staff                  4

示例3

如果我们要取 Ronald Trimp(PS)的子根,结果应该如下:

渴望输出

ID   Name           RoleCode    RoleDescription       ReportingtoID 
9    Kobe Spars       ST        Staff                  5

示例4

如果我们要取 Raymond Trimp(ST)的子根,结果应该如下:

由于ST是最低级别,因此不会显示任何记录。

渴望输出

ID   Name           RoleCode    RoleDescription       ReportingtoID 
                       No Record Found

我正在使用SQL Server 2016?需要帮助。有人可以为我做代码然后我会改进它。

1 个答案:

答案 0 :(得分:0)

Declare @YourTable table (ID int,Name varchar(50),RoleCode varchar(25),RoleDescription varchar(50),ReportingtoID  int)
Insert into @YourTable values 
(1   ,'Will Smith'       ,'PM'        ,'Project Manager'        ,NULL),
(2   ,'Zoey Nathan'      ,'PM'        ,'Project Manager'        ,NULL),
(3   ,'Louise Norton'    ,'PS'        ,'Project Supervisor'     ,1),
(4   ,'Cynthia Villaz'   ,'PS'        ,'Project Supervisor'     ,1),
(5   ,'Ronald Trimp'     ,'PS'        ,'Project Supervisor'     ,2),
(6   ,'Lebron James'     ,'ST'        ,'Staff'                  ,3),
(7   ,'Raymond Trimp'    ,'ST'        ,'Staff'                  ,4),
(8   ,'Kevin Garn'       ,'ST'        ,'Staff'                  ,3),
(9   ,'Kobe Spars'       ,'ST'        ,'Staff'                  ,5),
(10  ,'Paul Lee'         ,'ST'        ,'Staff'                  ,3),
(11  ,'Mark Pingris'     ,'ST'        ,'Staff'                  ,4),
(12  ,'Elton Horn'       ,'ST'        ,'Staff'                  ,1),
(13  ,'Shayne Wyn'       ,'ST'        ,'Staff'                  ,1)

Declare @Top  int         = null      --<<  Sets top of Hier Try 1 for Will Smith 
Declare @Leaf bit         = 0         --<<  Toggle Leaf Only
Declare @Nest varchar(25) = '|-----'  --<<  Optional: Added for readability

;with cteP as (
      Select Seq  = cast(10000+Row_Number() over (Order by Name) as varchar(500))
            ,ID
            ,ReportingtoID 
            ,Lvl=1
            ,Name
            ,RoleCode 
      From   @YourTable 
      Where  IsNull(@Top,-1) = case when @Top is null then isnull(ReportingtoID ,-1) else ID end
      Union  All
      Select Seq  = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.Name)) as varchar(500))
            ,r.ID
            ,r.ReportingtoID 
            ,p.Lvl+1
            ,r.Name
            ,r.RoleCode  
      From   @YourTable r
      Join   cteP p on r.ReportingtoID  = p.ID)
     ,cteR1 as (Select *,R1=Row_Number() over (Order By Seq) From cteP)
     ,cteR2 as (Select A.ID,R2=Max(B.R1) From cteR1 A Join cteR1 B on (B.Seq like A.Seq+'%') Group By A.Seq,A.ID )
Select A.R1  
      ,B.R2
      ,A.ID
      ,A.ReportingtoID 
      ,A.Lvl
      ,Name = case when @Leaf = 1 then '' else Replicate(@Nest,A.Lvl-1) end + A.Name
      ,A.RoleCode
 From  cteR1 A
 Join  cteR2 B on A.ID=B.ID
 Where A.R1 = case when @Leaf=1 then B.R2 else A.R1 end
 Order by case when @Leaf=1 then A.ID else A.R1 end

当@Top = 1且@Leaf = 1时,您将获得以下内容

enter image description here

当@Top = 1且@Leaf = 0时,您将获得嵌套层次结构

enter image description here

当@Top = NULL且@Leaf = 0时,您将获得FULL Hierarchy

enter image description here