在我的表中,每条记录都有一个指向他的直接父级的指针,我需要知道如何查询给定记录的所有后代,无论是直系还是非直系(儿子的儿子)。
事实:
- 我不知道树有多深,我需要所有的叶子
- 某些记录可能没有子记录
- 我在 SqlServer 2012 下运行
谁能告诉我如何编写这样的查询?
在我的表中,每条记录都有一个指向他的直接父级的指针,我需要知道如何查询给定记录的所有后代,无论是直系还是非直系(儿子的儿子)。
事实:
谁能告诉我如何编写这样的查询?
基于 Josh Wallace 的查询,获取后代。
declare @people table
(
Id int,
Name nvarchar(50),
ParentId int
)
insert into @people values (1, 'Frank', null)
insert into @people values (2, 'Shane', null)
insert into @people values (3, 'George', 1)
insert into @people values (5, 'Hank', 1)
insert into @people values (7, 'Abigail', 3)
insert into @people values (8, 'Ben', 3)
insert into @people values (9, 'Charlie', 5)
insert into @people values (10, 'Dave', 5)
insert into @people values (11, 'Homer', 5)
insert into @people values (12, 'Junebug', 7)
insert into @people values (13, 'Bart', 11)
insert into @people values (14, 'Lisa', 11)
;with descendents AS (
-- Anchor member definition
select p.Id, p.Name, p.ParentId, Level = 0
from @people p
where p.Id = 1 -- person to search for descendents
union all
-- Recursive member definition
select p.Id, p.Name, p.ParentId, Level + 1
from @people p
inner join descendents a on p.ParentId = a.Id
)
select
a.Level, ParentID = p.Id, Parent = p.Name, a.Id, Child = a.Name
from descendents a
left join @people p on p.Id = a.ParentId
order by a.Level
对我来说,使用 CTE 进行递归似乎是最简单的方法,这里有一个例子......
DECLARE @people TABLE
(
Id INT,
Name NVARCHAR(50),
ParentId INT
)
INSERT INTO @people (Id, Name, ParentId) VALUES (1, 'Abigail', null)
INSERT INTO @people (Id, Name, ParentId) VALUES (2, 'Ben', 5)
INSERT INTO @people (Id, Name, ParentId) VALUES (3, 'Charlie', 2)
INSERT INTO @people (Id, Name, ParentId) VALUES (4, 'Dave', 1)
INSERT INTO @people (Id, Name, ParentId) VALUES (5, 'Ed', 6)
INSERT INTO @people (Id, Name, ParentId) VALUES (6, 'Frank', null)
;WITH ancestors AS (
SELECT Id, Name, ParentId FROM @people WHERE Id = 3
UNION ALL
SELECT p.Id, p.Name, p.parentId FROM @people p
INNER JOIN ancestors a ON a.parentId = p.Id --This inner join causes the recurrsion
)
SELECT Id, Name, ParentId FROM ancestors
要从孩子到祖先,将 ON 语句切换为另一种方式:
DECLARE @people TABLE
(
Id INT,
Name NVARCHAR(50),
ParentId INT
)
INSERT INTO @people (Id, Name, ParentId) VALUES (1, 'Abigail', null)
INSERT INTO @people (Id, Name, ParentId) VALUES (2, 'Ben', 5)
INSERT INTO @people (Id, Name, ParentId) VALUES (3, 'Charlie', 2)
INSERT INTO @people (Id, Name, ParentId) VALUES (4, 'Dave', 1)
INSERT INTO @people (Id, Name, ParentId) VALUES (5, 'Ed', 6)
INSERT INTO @people (Id, Name, ParentId) VALUES (6, 'Frank', null)
;WITH ancestors AS (
SELECT Id, Name, ParentId FROM @people WHERE Id = 6
UNION ALL
SELECT p.Id, p.Name, p.parentId FROM @people p
--INNER JOIN ancestors a ON a.parentId = p.Id --It was this to go down...
INNER JOIN ancestors a ON a.Id = p.parentId --Now use this to go up the tree
)
SELECT Id, Name, ParentId FROM ancestors