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