SQL Server从父级和子级的层次表中获取数据

时间:2017-01-27 13:19:24

标签: sql sql-server common-table-expression

我像这里的树一样有桌子;

 Id ParentId Name
 -- -------- ---
  1 NULL      A
  2 1         B
  3 2         F
  4 3         C
  5 3         D
  6 1         E
  7 2         G
  8 NULL      M
  9 8         N
  10 8        O
  11 10       P


  1-A
    2-B
      3-F
        4-C
        5-D
      7-G
    6-E
  8-M
    9-N
    10-O
      11-P

到目前为止我已尝试过这个;

WITH     Relation (Id, ParentId, Name, [level], [orderSequence])
AS       (SELECT r.Id,
                 r.ParentId,
                 r.Name,
                 0,
                 CAST (r.Id AS VARCHAR (2500))
          FROM   Report AS r
          WHERE   r.Id = @rid
          UNION ALL
          SELECT p.Id,
                 p.ParentId,
                 p.Name,
                 rl.[level] + 1,
                 CAST (rl.orderSequence + '_' + CAST (p.Id AS VARCHAR) AS VARCHAR (2500))
          FROM   Report AS p INNER JOIN Relation AS rl ON p.ParentId = rl.Id)


SELECT   rl.* 
 FROM   relation AS rl

但它只返回孩子。 如何检查节点的所有父母与所有孩子 我希望获得节点Id = 3-F的样本输出;

Id ParentId Name
-- -------- ---
 1 NULL      A
 2 1         B
 3 2         F
 4 3         C
 5 3         D


1-A
  2-B
    3-F
      4-C
      5-D

2 个答案:

答案 0 :(得分:3)

Declare @Tags table (id int,ParentId  int,Name varchar(50))
Insert into @Tags values 
 (1, NULL      ,'A')
,(2, 1         ,'B')
,(3, 2         ,'F')
,(4, 3         ,'C')
,(5, 3         ,'D')
,(6, 1         ,'E')
,(7, 2         ,'G')
,(8, NULL      ,'M')
,(9, 8         ,'N')
,(10, 8        ,'O')
,(11, 10       ,'P')

Declare @Top    int         = null      --<<  Sets top of Hier Try 3 
Declare @Fetch  int         = null      --<<  Null for Entier Hier
Declare @Nest   varchar(25) = '|-----'  --<<  Optional: Added for readability

;with cteP as (
      Select Seq  = cast(1000+Row_Number() over (Order by Name) as varchar(500))
            ,ID
            ,ParentId 
            ,Lvl=1
            ,Name 
      From   @Tags 
      Where  IsNull(@Top,-1) = case when @Top is null then isnull(ParentId ,-1) else ID end
      Union  All
      Select Seq  = cast(concat(p.Seq,'.',1000+Row_Number() over (Order by r.Name)) as varchar(500))
            ,r.ID
            ,r.ParentId 
            ,p.Lvl+1
            ,r.Name 
      From   @Tags r
      Join   cteP p on r.ParentId  = 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 )
     ,cteHB as (
                Select A.R1  
                      ,B.R2
                      ,A.ID
                      ,A.ParentId 
                      ,A.Lvl
                      ,Name = Replicate(@Nest,A.Lvl-1) + concat(A.ID,'-',A.Name)
                 From cteR1 A
                 Join cteR2 B on A.ID=B.ID
               )
Select Distinct A.*
 From  cteHB A
 Join  cteHB B on B.ID = IsNull(@Fetch,A.ID) and (@Fetch is not null and A.R1 between B.R1 and B.R2 or B.R1 between A.R1 and A.R2) 
 Order By A.R1

<强>返回

enter image description here

其他选项:

设置@Fetch = NULL时,您将获得整个层次结构

enter image description here

答案 1 :(得分:2)

你只需要两个递归的CTE,一个用于父母,一个用于孩子:

declare @t table(Id int,ParentId int,Name nvarchar(1));
insert into @t values (1,NULL,'A'),(2,1,'B'),(3,2,'F'),(4,3,'C'),(5,3,'D'),(6 ,1,'E'),(7 ,2,'G'),(8 ,NULL,'M'),(9,8,'N'),(10,8,'O'),(11,10,'P');

declare @Id int = 3;

with Parents as
(
    select Id
            ,ParentId
            ,Name
    from @t
    where Id = @Id

    union all

    select t.Id
            ,t.ParentId
            ,t.Name
    from @t t
        inner join Parents p
            on t.Id = p.ParentId
),Children as
(
    select Id
            ,ParentId
            ,Name
    from @t
    where Id = @Id

    union all

    select t.Id
            ,t.ParentId
            ,t.Name
    from @t t
        inner join Children c
            on t.ParentId = c.Id
)
select *
from Parents

union all

select *
from Children
where Id <> @Id
order by Id;

输出:

+----+----------+------+
| Id | ParentId | Name |
+----+----------+------+
|  1 | NULL     | A    |
|  2 | 1        | B    |
|  3 | 2        | F    |
|  4 | 3        | C    |
|  5 | 3        | D    |
+----+----------+------+