树形数据的处理

原创 2003年12月29日 17:27:00

/*--表结构描述及数据环境:

 表名tb,如果修改表名,则相应修改所有数据处理中涉及到的表名tb
 id为编号(标识字段+主键),pid为上级编号,name为名称,后面可以自行增加其他字段. 
 凡是未特殊标注的地方,对自行增加的字段不影响处理结果

--邹建2003.12(引用请保留此信息)--*/

--测试数据
create table tb(
id int identity(1,1) not null constraint PK_tb primary key clustered,
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


--1.自定义函数--获取编码累计
create function f_getmergid(@id int)
returns varchar(8000)
as
begin
 declare @re varchar(8000),@pid int

 --为了数字排序正常,需要统一编码宽度
 declare @idlen int,@idheader varchar(20)
 select @idlen=max(len(id))
  ,@idheader=space(@idlen)
 from tb

 --得到编码累计
 set @re=right(@idheader+cast(@id as varchar),@idlen)
 select @pid=pid from tb where id=@id
 while @@rowcount>0
  select @re=right(@idheader+cast(@pid as varchar),@idlen)+','+@re
   ,@pid=pid from tb where id=@pid
 return(@re)
end
go


--2.自定义函数--检测某个编码出发,是否被循环引用
create function f_chkid(@id int)
returns bit --循环,返回1,否则返回0
as
begin
 declare @re bit,@pid int
 
 set @re=0

 --检测
 select @pid=pid from tb where id=@id
 while @@rowcount>0
 begin
  if @pid=@id
  begin
   set @re=1
   goto lbErr
  end
  select @pid=pid from tb where id=@pid
 end

lbErr:
 return(@re)
end
go

/*--数据复制

 如果表中包含自定义字段,需要修改存储过程
 存在嵌套不超过32层的问题.
--*/

--3.复制指定结点下的子结点到另一个结点下
create proc p_copy
@s_id int, --复制该项下的所有子项
@d_id int, --复制到此项下
@new_id int --新增加项的开始编号
as
declare @nid int,@oid int,@name varchar(20)
select id,name into #temp from tb where pid=@s_id and id<@new_id
while exists(select 1 from #temp)
begin
 select @oid=id,@name=name from #temp
 insert into tb values(@d_id,@name)
 set @nid=@@identity
 exec p_copy @oid,@nid,@new_id
 delete from #temp where id=@oid
end
go

--4.批量复制的存储过程--复制指定结点及其下面的所有子结点,并生成新结点
create proc p_copystr
@s_id varchar(8000) --要复制项的列表,用逗号分隔
as
declare @nid int,@oid int,@name varchar(20)
set @s_id=','+@s_id+','
select id,name into #temp from tb
where charindex(','+cast(id as varchar)+',', @s_id)>0
while exists(select 1 from #temp)
begin
 select @oid=id,@name=name from #temp
 insert into tb values(@oid,@name)
 set @nid=@@identity
 exec p_copy @oid,@nid,@nid
 delete from #temp where id=@oid
end
go

--5.得到指定id的子id列表
create function f_getchildid(@id int)
returns @re table(id int)
as
begin
 insert into @re select id from tb where pid=@id
 while @@rowcount>0
  insert into @re select a.id
   from tb a inner join @re b on a.pid=b.id
   where a.id not in(select id from @re)
 return
end
go


--6.得到指定id的父id列表
create function f_getparentid(@id int)
returns @re table(id int)
as
begin
 declare @pid int
 select @pid=pid from tb where id=@id
 while @pid<>0
 begin
  insert into @re values(@pid)
  select @pid=pid from tb where id=@pid
 end
 return
end
go


--7.删除指定结点

create proc p_delete
@id int,    --要删除的id
@deletechild bit=0  --是否删除子 1.删除子,0.如果@id有子,则删除失败.
as
 if @deletechild=1
  delete from tb where dbo.f_getmergid(id) like dbo.f_getmergid(@id)+'%'
 else
  if exists(select 1 from tb where pid=@id)
   goto lbErr
  else
   delete from tb where id=@id 
return

lbErr:
 RAISERROR ('该结点下有子结点,不能删除', 16, 1)
go


--8.得到编码累计及编码级别表,这个是针对全表的,主要是应该于全表处理:

create function f_getbmmerg()

returns @re table(id int,idmerg varchar(8000),level int)

as

begin
         declare @idlen int,@idheader varchar(20), @level int
         select @idlen=max(len(id)),@idheader=space(@idlen) from tb
         set @level=1
         insert into @re select id,right(@idheader+cast(id as varchar),@idlen),@level
                   from tb where pid=0
         while @@rowcount>0
         begin
                   set @level=@level+1
                   insert into @re select b.id,a.idmerg+','+right(@idheader+cast(b.id as varchar),@idlen),@level
                            from @re a inner join tb b on a.id=b.pid
                            where a.level=@level-1
         end
return
end
go


--应用:

/*--数据显示排序--*/
--分级显示--横向,先一级,后二级...
select * from tb order by pid

--分级显示--纵向
select * from tb order by dbo.f_getmergid(id)
go

/*--数据统计--*/
--分级统计,每个地区下的明细地区数

select *,
 明细地区数=(select count(*) from tb where dbo.f_getmergid(id) like dbo.f_getmergid(a.id)+',%')
from tb a order by dbo.f_getmergid(id)

go
/*--数据新增,修改
 
 数据新增,修改(包括修改所属的类别)没有什么技巧
 ,只需要检查所属的上级是否存在就行了.这个可以简单的用下面的语句来解决:
 if exists(select 1 from tb where
id=@id) print '存在' else print '不存在'
--*/


--删除'美国'的数据
--exec p_delete 2  --不包含子,因为有美国下有子,所以删除会出错
exec p_delete 2,1 --包含子,将删除美国及所有数据
go


原文参见我在CSDN上发表的贴子

http://expert.csdn.net/Expert/topic/2285/2285830.xml?temp=.1212885

树形结构JSON的实现方法(也叫做JSON嵌套格式)

在Web应用程序开发领域,基于Ajax技术的JavaScript树形控件已经被广泛使用,它用来在Html页面上展现具有层次结构的数据项。目前市场上常见的JavaScript框架及组件库中均包含自己的树...
  • u010805500
  • u010805500
  • 2013年05月30日 15:17
  • 1495

如何将数据库中存的树转化为树形列表(以easyui的tree为例)

很多时候,我们会把一棵树存放到数据库中,当前台需要展示一个树形列表时,将这棵树读取出来并显示,这个过程是怎么实现的呢? 这篇文章是以构造一棵easyui前台框架的一个树形列表为例,后台框架是spri...
  • u012116457
  • u012116457
  • 2015年05月22日 09:20
  • 10417

树形数据的处理

/*--表结构描述及数据环境: 表名tb,如果修改表名,则相应修改所有数据处理中涉及到的表名tb id为编号(标识字段+主键),pid为上级编号,name为名称,后面可以自行增加其他字段.  凡是未特...
  • zjcxc
  • zjcxc
  • 2003年12月29日 17:27
  • 8118

树形结构数据后台处理:一次循环生成树

▼    //一、优化算法下的树结构遍历   @SuppressWarnings("unchecked")  public String gainTreeFolder(){   //1 设...
  • u012843873
  • u012843873
  • 2016年04月28日 11:36
  • 408

树形数据的处理

/*--表结构描述及数据环境: 表名tb,如果修改表名,则相应修改所有数据处理中涉及到的表名tb id为编号(标识字段+主键),pid为上级编号,name为名称,后面可以自行增加其他字段.  凡是未特...
  • chenzhiya
  • chenzhiya
  • 2008年01月03日 15:51
  • 151

【java基础 3】树形结构数据呈现的递归算法实现

一、基本概况 在我的项目中,常常会用到树形结构的数据,最为明显的就是左边菜单栏,类似于window folder一样的东西。 而我之前一直是借助前端封装好的ZTree等工具实现展示,而后台则通常使...
  • u013034889
  • u013034889
  • 2016年08月27日 18:12
  • 5966

海量数据处理之Tire树(字典树)

参考博文:http://blog.csdn.net/v_july_v/article/details/6897097 第一部分、Trie树 1.1、什么是Trie树     Trie树,即字典树...
  • ts173383201
  • ts173383201
  • 2012年08月13日 09:02
  • 18893

大数据的处理方法<一>

处理海量数据问题,无非就是: 分而治之/hash映射 + hash统计 + 堆/快速/归并排序...
  • gogoky
  • gogoky
  • 2016年05月03日 14:19
  • 592

SQL树形数据的处理

/*--表结构描述及数据环境: 表名tb,如果修改表名,则相应修改所有数据处理中涉及到的表名tb id为编号(标识字段+主键),pid为上级编号,name为名称,后面可以自行增加其他字段.  凡是未特...
  • jackeyabc
  • jackeyabc
  • 2007年03月19日 15:24
  • 765

Java - 树状结构数据解析

由于工作中好多地方需要树状结构数据,在参考了网上递归实现和数据库存储过程实现,都不太满意。突然想到zTree也有解析该类数据的要求,所以在阅读了zTree源码的前提了,按照他的实现原理,写了一个jav...
  • yb642518034
  • yb642518034
  • 2016年10月15日 19:27
  • 1284
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:树形数据的处理
举报原因:
原因补充:

(最多只允许输入30个字)