最近,在论坛中,遇到了不少比较难的sql问题,虽然自己都能解决,但发现过几天后,就记不起来了,也忘记解决的方法了。
所以,觉得有必要记录下来,这样以后再次碰到这类问题,也能从中获取解答的思路。
问题:求SQL:检索某个节点下所有叶子节点
部门表名:tb_department
id int --节点id
pid int --父节点id
caption varchar(50) --部门名称
-------------------------------------
id pid caption
----------------------------------------------
1 0 AA
20 1 BB
64 20 CC
22 1 DD
23 22 EE
24 1 FF
25 0 GG
26 1 HH
27 25 II
----------------树状结构如下----------------
--------------------------------------
问:怎么检索出某个节点下的所有最尾端的叶子节点。
例如:想检索AA节点下的所有尾端节点CC,EE,FF,HH?
我的解法,适合sql server 2005及以上的 版本:
create table tb_department(
id int, --节点id
pid int, --父节点id
caption varchar(50) --部门名称
)
insert into tb_department
select 1 ,0 ,'AA' union all
select 20 ,1 ,'BB' union all
select 64 ,20 ,'CC' union all
select 22 , 1 ,'DD' union all
select 23 , 22 ,'EE' union all
select 24 , 1 ,'FF' union all
select 25 , 0 ,'GG' union all
select 26 , 1 ,'HH' union all
select 27 , 25 ,'II'
go
;with t
as
(
select id,pid,caption
from tb_department
where caption = 'AA'
union all
select t1.id,t1.pid,t1.caption
from t
inner join tb_department t1
on t.id = t1.pid
)
select *
from t
where not exists(select 1 from tb_department t1 where t1.pid = t.id)
/*
id pid caption
24 1 FF
26 1 HH
23 22 EE
64 20 CC
*/
如果是sql server 2000呢,要怎么写呢:
--1.建表
create table tb_department(
id int, --节点id
pid int, --父节点id
caption varchar(50) --部门名称
)
insert into tb_department
select 1 ,0 ,'AA' union all
select 20 ,1 ,'BB' union all
select 64 ,20 ,'CC' union all
select 22 , 1 ,'DD' union all
select 23 , 22 ,'EE' union all
select 24 , 1 ,'FF' union all
select 25 , 0 ,'GG' union all
select 26 , 1 ,'HH' union all
select 27 , 25 ,'II'
go
--2.定义表变量
declare @tb table
(id int, --节点id
pid int, --父节点id
caption varchar(50), --部门名称
level int --层级
)
--3.递归开始
insert into @tb
select *,1 as level
from tb_department
where caption = 'AA'
--4.递归的过程
while @@ROWCOUNT > 0
begin
insert into @tb
select t1.id,t1.pid,t1.caption,level + 1
from @tb t
inner join tb_department t1
on t.id = t1.pid
where not exists(select 1 from @tb t2
where t.level < t2.level)
end
--5.最后查询
select *
from @tb t
where not exists(select 1 from tb_department t1 where t1.pid = t.id)
/*
id pid caption level
24 1 FF 2
26 1 HH 2
64 20 CC 3
23 22 EE 3
*/