分享
 
 
 

完整路径在树型结构表中的应用

王朝other·作者佚名  2006-06-09
窄屏简体版  字體: |||超大  

在MIS系统开发过程中经常使用树型结构表,如人力资源模块的部门表、财务模块的会计科目表等,传统的做法是从编码上体现一种树型父子关系,并约定每节的字长,这种做法强制用户按照程序既定的规则,用户没有选择编码规则的自由,扩展性差。为了解决这个问题,一般会在表中建两个栏位(或类似栏位):id和parent_id,用于表述两条数据间的树型父子关系,但这带来的负作用是查询非直接父项或子项时需要使用递归算法或循环,性能上并不令人满意。如果在此基础上增加一个完整路径的栏位(能够完整描述一个项目的路径的栏位,类似操作系统的文件全路径),则查询性能会明显提高。

我们以一个部门表为例。

CREATE TABLE [hrm_dept] (

[dept_code] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,

[dept_name] [varchar] (40) COLLATE Chinese_PRC_CI_AS NOT NULL ,

[parent_dept_code] [varchar] (20) COLLATE Chinese_PRC_CI_AS NULL,

[dept_path] [varchar] (8000) COLLATE Chinese_PRC_CI_AS NULL ,

CONSTRAINT [PK_hrm_dept] PRIMARY KEY CLUSTERED

(

[dept_code]

) ON [PRIMARY]

) ON [PRIMARY]

其中:dept_code表示部门编号,dept_name表示部门名称,parent_dept_code表示父部门编号,dept_path表示部门路径(由触发器维护)。

用户的需求是根据输入的部门编号获取该部门的所有子部门(直接和间接)。

如果没有dept_path栏位或不利用dept_path栏位,我们所创建的获取指定部门的所有子部门的函数可能会这样写。

CREATE FUNCTION udf_hrm_getchilddept (@dept_code varchar(20))

RETURNS @tab_childdept TABLE (parent_dept_code varchar(20),child_dept_code varchar(20))

AS

/*

名称: udf_hrm_getchilddept

功能描述: 取指定部门的所有子部门

涉及对象: hrm_dept 部门表

实现方法简述:递归取子部门

输入参数: @dept_code 部门编号

输出内容: 指定部门的所有子部门

创建人员: 康剑民

创建日期: 2006-06-06

*/

BEGIN

---定义临时表以存储子部门数据

declare @temp_childdept table

(row_id int IDENTITY(1, 1) not null

,parent_dept_code varchar(20) not null

,child_dept_code varchar(20) not null)

declare @child_dept_code varchar(20),--子部门编号

@max_row_id int,---插入的最大行号

@loop_row_id int---循环行号

---插入直接子部门数据

insert into @tab_childdept

(parent_dept_code

,child_dept_code)

select @dept_code

,dept_code

from hrm_dept

where parent_dept_code = @dept_code

---插入直接子部门数据到临时表

insert into @temp_childdept

(parent_dept_code

,child_dept_code)

select @dept_code

,dept_code

from hrm_dept

where parent_dept_code = @dept_code

---取最大行号和最小行号

select @max_row_id = max(row_id),

@loop_row_id = min(row_id)

from @temp_childdept

if @loop_row_id is null or @loop_row_id = 0 select @loop_row_id=1

---循环取子部门数据

while @loop_row_id <= @max_row_id

begin

select @child_dept_code = child_dept_code

from @temp_childdept

where row_id = @loop_row_id

---插入子部门的子部门数据

insert into @tab_childdept

(parent_dept_code

,child_dept_code)

select parent_dept_code

,child_dept_code

from dbo.udf_hrm_getchilddept(@child_dept_code)

---循环变量步进自增

select @loop_row_id = @loop_row_id + 1

end

return

end

如果使用部门路径栏位,则该函数可以按如下改造。

CREATE FUNCTION udf_hrm_getchilddept2 (@dept_code varchar(20))

RETURNS @tab_childdept TABLE (parent_dept_code varchar(20),child_dept_code varchar(20))

AS

/*

名称: udf_hrm_getchilddept

功能描述: 取指定部门的所有子部门

涉及对象: hrm_dept 部门表

实现方法简述:根据部门路径取子部门

输入参数: @dept_code 部门编号

输出内容: 指定部门的所有子部门,返回表栏位含义:

parent_dept_code 父部门编号

child_dept_code 子部门编号

创建人员: 康剑民

创建日期: 2006-06-06

*/

BEGIN

declare @dept_path varchar(8000)--部门路径

--取部门路径

select @dept_path = dept_path

from hrm_dept

where dept_code = @dept_code

--插入子部门数据(直接和间接)

insert into @tab_childdept

(parent_dept_code

,child_dept_code)

select parent_dept_code

,dept_code

from hrm_dept

where dept_path like @dept_path + '/%'

在此我们假设dept_path使用’/’分隔部门编号。

经测试,方法二明显性能提高。以笔者的测试样例数据,获取子部门数同样为727条,方法一需要3646毫秒,方法二只需要20毫秒,方法一所用时间是方法二的182倍。如果dept_path栏位长度可以控制在900个字节以内(MSSQLSERVER限制)并在其上加索引,则速度更快。注:不同的测试环境,样例测试数据可能不同,但结论是相同的,那就是方法二性能好。

根据指定的项目取所有父项目的方法类似。

当然,如果使用完整路径,应该在表的插入、修改、删除触发中维护完整路径的值,维护的代价不高,但查询速度得到大幅度提高,如果这个树型结构表不是频繁地插入、修改、删除数据而是查询的机会多的话,这种优化方法是值得去做的。另外还要注意几点:如果生成完整路径的字符过长,可以采用text类型;完整路径所依赖的栏位不能使用程序所使用的分隔符。

写作日期:2006-06-06

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有