【MySQL疑难杂症】如何将树形结构存储在数据库中(方案三 Closure Table)

【MySQL疑难杂症】如何将树形结构存储在数据库中(方案三 Closure Table)

2017.12.18 12:01 2071浏览

【MySQL疑难杂症】如何将树形结构存储在数据库中系列篇

如何将树形结构存储在数据库中(方案一 Adjacency List)

如何将树形结构存储在数据库中(方案二Path Enumeration)

如何将树形结构存储在数据库中(方案三 Closure Table)

今天介绍将树形结构存储在数据库中的第三种方法——终结表(原谅我这生硬的翻译。。)。

继续用上一篇的栗子,下面是要存储的结构图:

图片描述

需要回答的问题依旧是这样几个:

1.查询小天的直接上司。

2.查询老宋管理下的直属员工。

3.查询小天的所有上司。

4.查询老王管理的所有员工。

方案三、Closure Table 终结表法,保存每个节点与其各个子节点的关系,也就是记录以其为根节点的全部子节点信息。直接上代码就明白了:

这里要创建两个表,一个表用来存储信息:

CREATE TABLE employees3(
eid INT,
ename VARCHAR(100),
position VARCHAR(100)
)

一个表用来存储关系:

CREATE TABLE emp_relations(
root_id INT,
depth INT,
is_leaf TINYINT(1),
node_id INT
)

这里的root_id用来存放以其为根节点的路径,node_id表示节点处的eid,depth表示根节点到该节点的深度,is_leaf表示该节点是否为叶子节点。

接下来插入数据:

图片描述
图片描述

可以看出,这个关系表有点大,我们先来看看查询效果如何:

1.查询小天的直接上司。

这里只需要在关系表中找到node_id为小天id,depth为1的根节点id即可。

SELECT e2.ename BOSS FROM employees3 e1,employees3 e2,emp_relations rel 
WHERE e1.ename='小天' AND rel.node_id=e1.eid AND rel.depth=1 AND e2.eid=rel.root_id

查询结果如下:


图片描述

2.查询老宋管理下的直属员工。

思路差不多,只要查询root_id为老宋eid且深度为1的node_id即为其直接下属员工id

SELECT e1.eid,e1.ename 直接下属 FROM employees3 e1,employees3 e2,emp_relations rel 
WHERE e2.ename='老宋' AND rel.root_id=e2.eid AND rel.depth=1 AND e1.eid=rel.node_id

查询结果如下:


图片描述

3.查询小天的所有上司。

只要在关系表中找到node_id为小天eid且depth大于0的root_id即可

SELECT e2.eid,e2.ename 上司 FROM employees3 e1,employees3 e2,emp_relations rel 
WHERE e1.ename='小天' AND rel.node_id=e1.eid AND rel.depth>0 AND e2.eid=rel.root_id

查询结果如下:

图片描述

4.查询老王管理的所有员工。

只要在关系表中查找root_id为老王eid,depth大于0的node_id即可

SELECT e1.eid,e1.ename 下属 FROM employees3 e1,employees3 e2,emp_relations rel 
WHERE e2.ename='老王' AND rel.root_id=e2.eid AND rel.depth>0 AND e1.eid=rel.node_id

查询结果如下:

图片描述

我们可以发现,这四个查询的复杂程度是一样的,这就是这种存储方式的优点,而且可以让另一张表只存储跟节点紧密相关的信息,看起来更简洁。但缺点也显而易见,关系表会很庞大,当层次很深,结构很庞大的时候,关系表数据的增长会越来越快,相当于用空间效率来换取了查找上的时间效率。

至此,树形结构在数据库中存储的三种方式就介绍完了,接下来对比一下三种方法:

方案一:Adjacency List

优点:只存储上级id,存储数据少,结构类似于单链表,在查询相邻节点的时候很方便。添加删除节点都比较简单。

缺点:查询多级结构的时候会显得力不从心。

适用场合:对多级查询需求不大的场景比较适用。

方案二:Path Enumeration

优点:查询多级结构的时候比较方便。查询相邻节点时也比较ok。增加或者删除节点的时候比较简单。

缺点:需要存储的path值可能会很大,甚至超过设置的最大值范围,理论上无法无限扩张。

适用场合:结构相对简单的场景比较适合。

方案三:Closure Table

优点:在查询树形结构的任意关系时都很方便。

缺点:需要存储的数据量比较多,索引表需要的空间比较大,增加和删除节点相对麻烦。

适用场合:纵向结构不是很深,增删操作不频繁的场景比较适用。

当然,也可以再自己创新出其他更好的存储方案,如果有更好的想法,欢迎提出交流。

至此三种方案全部介绍完毕,欢迎大家继续关注。

真正重要的东西,用眼睛是看不见的。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 程序设计中常使用树型结构来表征某些数据的关联关系,如上下级、栏目结构、商品分类、菜单、回复等。 分类的层级关系可以...
    JunChow520阅读 4,136评论 4 3
  • 我们时常会遇到这样的场景,如:组织结构图、回复评论的评论链、用于组织资源的树形资源组。 如图: 而作为一名程序员如...
    点融黑帮阅读 25,425评论 4 37
  • 我们常常用树形结构来表征某些数据的关联关系,如企业上下级部门、栏目结构、商品分类等等,通常而言,这些树状结构需要借...
    Tucke阅读 4,137评论 0 52
  • 今天看到一位朋友写的mysql笔记总结,觉得写的很详细很用心,这里转载一下,供大家参考下,也希望大家能关注他原文地...
    信仰与初衷阅读 4,768评论 0 30
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,492评论 0 9