数据库中树型结构的一个变种存储方式

数据库中,树型结构的存储方式,一般有三种,相邻表,路径关联,闭包表,

这三种方法无非解决两个问题,
1. 结点的信息存储
2. 明确结点之间的关系

同时又会导致查询和更新操作之间的对立,为什么这么说,简单介绍一下,上述三种方法,

相邻表,除了结点信息,只存储父节点的编号,根节点的父节点为0,

路径关联,使用文本方式,记录结点的路径,比如/1/2/5/7/9,表示结点1-2-5-7-9是一条连续的结点路径,

闭包表,以上两种方法,只有一张表,闭包表则使用两张表,一表保存结点信息,一表保存结点间的关系,在关系表中,将会完整记录所有结点间的关系,包括根节点与每个底层结点的关系,这显然存在巨大的数据冗余

--------------------------------------------------------------------------------------
由于结点之间的复杂关系,带来一个问题,如何描述,如果简单描述,比如相邻表和路径关联,
在查询根节点的所有后代结点时,将涉及到循环查询,以及路径文本串的解析,
同时又获得了快速更新的优势,

在闭包表中,利用关系表,只需一次查询,就可得到根节点的所有后代结点,
但是在更新时,由于数据冗余太大,需要同步的关系数据,则相当多,因此更新的开销很大,

------------------------------------------------------------------------------------------------

综合上述方法,得到一个变种,同时满足查询和更新的便利,以及减少存储空间的浪费,
为了结构更清晰,使用两张表,当然也可以选择一张表,

CREATE TABLE TreeNode (
nid int,
name VARCHAR(100),
desc VARCHAR(100)
)

CREATE TABLE TreeRelationship (
nid int,
prior_id int,
next_id int
)

nid - 结点的数字编码
name - 结点的信息存储
desc - 结点的文本描述
prior_id - 当前结点的上代结点
next_id - 当前结点的后代结点

在关系表中,增加上代结点和后代结点,极大减少了闭包中,从根节点到当前节点的路径记录,
同时更新更加便利,比如插入操作,只需修改上代结点的next_id,后代结点的prior_id, 再保存
插入结点的数据即可,

闭包表的优势在于,快速查询某个结点的跨代结点,在变种中,引入desc,即结点的文本描述,

例如一个公司的职位架构,

董事长
总经理
技术部经理/产品部经理/公共部经理/人事部经理
---------------------------------------------------------------
技术部经理
技术部项目A主管/技术部项目B主管/技术部项目C主管
----------------------------------------------------------------
技术部项目A主管
技术部项目A组长
技术部项目A员工/技术部项目A员工/技术部项目A员工/技术部项目A员工/技术部项目A员工/技术部项目A员工/技术部项目A员工/技术部项目A员工


一个公司的职位架构,一般情况下,比较固定,可以基于这些职位名,
进行后代结点的查询,也就是说,利用desc的文本描述,将结点进行分区,
得到一个抽象的区域连接,使得跨代查询更加简单高效,当然与路径关联的方法,
十分相似的,

因此可以查询“技术部”,“项目A”

----------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------
在相邻表的学习中,遇到一个问题,无论是中文页面,还是英文页面,都没有讨论这个问题,
也许是资源不够充分,

   A
 /    \
B    C

在上述相邻表的结点中,需要插入一个D结点,那么问题来了,一个插入函数,
如何判断,插入B或C之前,还是插入A之后,因为相邻表只有父节点的指示,
无法实现后向插入,只能在插入函数中,传入标志位,或者使用两个插入函数。

    A
   /   \
 D    \
 /       \
B       C

 A
  |
 D
 /  \
B  C

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值