Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server从具有父级和子级的分层表中获取数据_Sql_Sql Server_Common Table Expression - Fatal编程技术网

SQL Server从具有父级和子级的分层表中获取数据

SQL Server从具有父级和子级的分层表中获取数据,sql,sql-server,common-table-expression,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

我有一张像树一样的桌子

 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
但它只返回childs。 如何检索节点的所有父节点和所有子节点 我想要为节点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

您只需要两个递归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;
Declare@Tags表(id int,ParentId int,Name varchar(50))
插入@Tags值
(1,NULL,'A')
,(2,1,'B')
,(3,2,'F')
,(4,3,'C')
,(5,3,'D')
,(6,1,'E')
,(7,2,'G')
,(8,空,'M')
,(9,8,'N')
,(10,8,'O')
,(11,10,'P')

声明@Top int=null——我认为您必须合并两个递归CTE——一个用于获取树节点的后代,另一个用于获取前辈。谢谢您的回答!使用,您可以从结果网格复制并将其粘贴到输入中,然后单击“创建表格”以获得表格的代码格式友好版本,而不是使用图像。@SqlZim否,我更喜欢图像。这是一个更好的视觉效果
+----+----------+------+
| Id | ParentId | Name |
+----+----------+------+
|  1 | NULL     | A    |
|  2 | 1        | B    |
|  3 | 2        | F    |
|  4 | 3        | C    |
|  5 | 3        | D    |
+----+----------+------+
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