取树中某一节点的所有子节点的存储过程~!
我有一个表,为树型数据设计的。
里面有字段dealerid(节点编号),parentid(父节点标号)等字段。
希望做一个存储过程,给任一节点的编号,然后找出其所有子节点的节点编号。
这个存储过程该如何写法,希望邹建等高手帮一下忙!!
如果所给的节点的个数不定(所给节点通过某一条件查询查出,可以有多条结果),要找出所有这些节点的子节点数据的union。
这个存储过程又该怎么写啊?
问题点数:168、回复次数:9Top
1 楼jinjazz(近身剪)回复于 2005-04-01 14:40:15 得分 50
转贴一个~~
--示例
--测试数据
create table tb(父项 varchar(10),子项 varchar(10))
insert tb select 'a001','A1'
union all select 'a001','D1'
union all select 'a001','E1'
union all select 'A1' ,'B1'
union all select 'A1' ,'C1'
union all select 'E1' ,'C1'
union all select 'E1' ,'D1'
union all select 'E1' ,'F1'
go
--查询处理函数
create function f_id()
returns @re table(子项 varchar(10),[level] int,sid varchar(8000))
as
begin
declare @l int
set @l=1
insert @re select distinct 父项,@l,父项
from tb a
where not exists(select * from tb where 子项=a.父项)
while @@rowcount>0
begin
set @l=@l+1
insert @re select a.子项,@l,b.sid+'>'+a.子项
from tb a,@re b
where a.父项=b.子项 and b.[level]=@l-1
end
return
end
go
--调用函数实现分级显示
select 层号=level,[部件号(产品号)]=子项
from f_id()
order by sid
go
--删除测试
drop table tb
drop function f_id
/*--结果
层号 部件号(产品号)
----------- ----------
1 a001
2 A1
3 B1
3 C1
2 D1
2 E1
3 C1
3 D1
3 F1
(所影响的行数为 9 行)
--*/
Top
2 楼zjcxc(邹建)回复于 2005-04-01 14:47:25 得分 118
--树形数据查询示例
--作者: 邹建
if exists (select * from dbo.sysobjects where id = object_id(N'[tb]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [tb]
GO
--示例数据
create table [tb]([id] int identity(1,1),[pid] int,name varchar(20))
insert [tb] select 0,'中国'
union all select 0,'美国'
union all select 0,'加拿大'
union all select 1,'北京'
union all select 1,'上海'
union all select 1,'江苏'
union all select 6,'苏州'
union all select 7,'常熟'
union all select 6,'南京'
union all select 6,'无锡'
union all select 2,'纽约'
union all select 2,'旧金山'
go
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[f_cid]') and xtype in (N'FN', N'IF', N'TF'))
drop function [dbo].[f_cid]
GO
/*--树形数据处理
查询指定id的所有子
--邹建 2003-12(引用请保留此信息)--*/
/*--调用示例
--调用(查询所有的子)
select a.*,层次=b.[level] from [tb] a,f_cid(2)b where a.[id]=b.[id]
--*/
create function f_cid(
@id int
)returns @re table([id] int,[level] int)
as
begin
declare @l int
set @l=0
insert @re select @id,@l
while @@rowcount>0
begin
set @l=@l+1
insert @re select a.[id],@l
from [tb] a,@re b
where a.[pid]=b.[id] and b.[level]=@l-1
end
return
end
go
--调用(查询所有的子)
select a.*,层次=b.[level] from [tb] a,f_cid(2)b where a.[id]=b.[id]
goTop
3 楼zjcxc(邹建)回复于 2005-04-01 14:54:36 得分 0
--如果所给的节点个数不定,那就要看你的参数是如何传递
--假设你通过一个字符串来传递,则可以这样写存储过程
--示例数据
create table [tb](dealerid int identity(1,1),parentid int,name varchar(20))
insert [tb] select 0,'中国'
union all select 0,'美国'
union all select 0,'加拿大'
union all select 1,'北京'
union all select 1,'上海'
union all select 1,'江苏'
union all select 6,'苏州'
union all select 7,'常熟'
union all select 6,'南京'
union all select 6,'无锡'
union all select 2,'纽约'
union all select 2,'旧金山'
go
--查询处理的存储过程
create proc p_qry
@idlist varchar(8000) --要查询的id列表
as
set nocount on
declare @l int
set @l=0
create table #t(dealerid_qry int,dealerid int,level int)
insert #t select dealerid,dealerid,@l
from tb
where charindex(','+cast(dealerid as varchar)+',',','+@idlist+',')>0
while @@rowcount>0
begin
set @l=@l+1
insert #t select b.dealerid_qry,a.dealerid,@l
from tb a,#t b
where a.parentid=b.dealerid and b.level=@l-1
end
select b.dealerid_qry,a.*
from tb a,#t b
where a.dealerid=b.dealerid
order by b.dealerid_qry
go
--调用实现查询
exec p_qry '2,1,5'
go
--删除测试
drop table tb
drop proc p_qry
/*--结果
dealerid_qry dealerid parentid name
------------ ----------- ----------- --------------------
1 4 1 北京
1 5 1 上海
1 6 1 江苏
1 9 6 南京
1 10 6 无锡
1 7 6 苏州
1 8 7 常熟
1 1 0 中国
2 2 0 美国
2 11 2 纽约
2 12 2 旧金山
5 5 1 上海
--*/
Top
4 楼zjcxc(邹建)回复于 2005-04-01 14:57:21 得分 0
--如果所给的节点个数不定,假设你通过一个字符串来传递,则可以这样写存储过程
--如果要求查询结果只包含dealerid不重复的,则改为
--示例数据
create table [tb](dealerid int identity(1,1),parentid int,name varchar(20))
insert [tb] select 0,'中国'
union all select 0,'美国'
union all select 0,'加拿大'
union all select 1,'北京'
union all select 1,'上海'
union all select 1,'江苏'
union all select 6,'苏州'
union all select 7,'常熟'
union all select 6,'南京'
union all select 6,'无锡'
union all select 2,'纽约'
union all select 2,'旧金山'
go
--查询处理的存储过程
create proc p_qry
@idlist varchar(8000) --要查询的id列表
as
set nocount on
declare @l int
set @l=0
create table #t(dealerid int,level int)
insert #t select dealerid,@l
from tb
where charindex(','+cast(dealerid as varchar)+',',','+@idlist+',')>0
while @@rowcount>0
begin
set @l=@l+1
insert #t select a.dealerid,@l
from tb a,#t b
where a.parentid=b.dealerid and b.level=@l-1
end
select a.*
from tb a,(select distinct dealerid from #t)b
where a.dealerid=b.dealerid
go
--调用实现查询
exec p_qry '2,1,5'
go
--删除测试
drop table tb
drop proc p_qry
/*--结果
dealerid parentid name
----------- ----------- --------------------
1 0 中国
2 0 美国
4 1 北京
5 1 上海
6 1 江苏
7 6 苏州
8 7 常熟
9 6 南京
10 6 无锡
11 2 纽约
12 2 旧金山
--*/
Top
5 楼TigerSuper(菜鸟(鸟吃菜吗?))回复于 2005-04-01 14:58:40 得分 0
UP
怎么实现个数不确定节点的查询?Top
6 楼lovvver(ElephantTalk.Bright)回复于 2005-04-01 15:01:05 得分 0
因为我在做一个客户关系管理的东西,
这个树的层次就大概5-6层的样子,每层有具体名字,
如Fiscal unit,reseller,agent group,agent,sub-agent等。
每个用户(系统用户)有可能有几个身份(对应这个树的几个节点)。
我希望登陆以后,这个用户能够看到他所有下级节点。
因此我首先要根据登陆信息找到登陆用户的节点(>=1个),然后再根据这些节点找到这些节点对应的所有子节点的集合(DATASET)
希望能够用存储过程实现为好。
多谢了。~~
Top
7 楼zjcxc(邹建)回复于 2005-04-01 15:06:06 得分 0
后面的就是存储过程的处理方法,先参考,解决不了再根据实际情况问Top
8 楼lovvver(ElephantTalk.Bright)回复于 2005-04-01 15:12:08 得分 0
多谢邹老大和各位老兄!~
我得研究一下,啊哈~Top
9 楼winternet(冬天)回复于 2005-04-01 15:54:51 得分 0
upTop




