数据库分层数据现实方法

分层数据

  • 分层数据的每项(除根项)只有一个父项和零个或多个子项的数据集合。
  • 分层数据存在于许多基于数据库的应用程序中,包括论文和邮件列表中的分类、组织层级关系、内容管理系统的分类、产品分类。

邻接表模型

数据库中结构:

+--------+----------------------+--------------+
|          id | name            | parent_id    |
+-------------+-----------------+--------------+
|           1 | 智慧学校          |     NULL    |
|           2 | 广东省教育厅       |      1      |
|           3 | 广州市教育厅       |      2      |
|           4 | 东莞市教育厅       |      2      |
|           5 | 佛山市教育厅       |      2      |
|           6 | 荔湾区华侨小学     |      3      |
|           7 | 湖南省教育厅       |      1      |
|           8 | 长沙市教育厅       |      7      |
|           9 | 湘潭市教育厅       |      7      |
|         10  | 张家界市教育厅     |      7      |
+-------------+----------------------+--------+

优点:
实现简单,能直观看到直接父子关系。
缺点:
当要检索某节点下所有子孙节点时,只能一层一层递归查询。

orcal中实现子孙节点查找:
SELECT * FROM unit t CONNECT BY prior t.parent_id=t.id start with t.parent_id = 1
mysql使用函数实现(使用函数形式):

CREATE FUNCTION getChildLst(id INT)
  RETURNS varchar(1000) CHARSET utf8
BEGIN 
       DECLARE sTemp VARCHAR(1000); 
       DECLARE sTempChd VARCHAR(1000); 

       SET sTemp = '$'; 
       SET sTempChd =cast(rootId as CHAR); 

       WHILE sTempChd is not null DO 
         SET sTemp = concat(sTemp,',',sTempChd); 
         SELECT group_concat(id) INTO sTempChd FROM emp where FIND_IN_SET(parentId,sTempChd)>0; 
       END WHILE; 
       RETURN substr(sTemp,3); 
     END

看上面的语句是全表扫描,没有走索引。一些数据量比较大的表,查询就很慢。

前缀编码模型

数据库结构

+-------------+-----------------+--------+
|          id | name             | code |
+--------+----------------------+--------+
|           1 | Seewo智慧学校     |  001 |
|           2 | 广东省教育厅       |  001001 |
|           3 | 广州市教育厅       |  001001001 |
|           4 | 东莞市教育厅       |  001001002 |
|           5 | 佛山市教育厅       |  001001003 |
|           6 | 荔湾区华侨小学     |  001001001001 |
|           7 | 湖南省教育厅       |  001002 |
|           8 | 长沙市教育厅       |  001002001 |
|           9 | 湘潭市教育厅       |  001002002 |
|          10 | 张家界市教育厅      | 001002003 |
+-------------+----------------------+--------+

节点编码:为当前记录行的编码(内部编码),它的所有直接下级记录行的编码都是以它为依据进行扩展。
优点:
使用like语句即可查出其所有子孙节点的记录集。
缺点:
固定长度编码限制了子节点的个数,层级不明显,查询直系亲属节点麻烦。
每层的节点个数受编码长度限制

改进的前缀编码模型

数据库结构

+--------+------------------+----------------+--------------+--------------+
|     id | name             | parent_id      | code         |  childMaxNum |
+--------+------------------+----------------+--------------+--------------+
|      1 | Seewo智慧学校     |     NULL        |  1.         |      2        |
|      2 | 广东省教育厅       |      1          |  1.1.       |      3        |
|      3 | 广州市教育厅       |      2          |  1.1.1.     |      1        |
|      4 | 东莞市教育厅       |      2          |  1.1.2.     |      0        |
|      5 | 佛山市教育厅       |      2          |  1.1.3.     |      0        |
|      6 | 荔湾区华侨小学     |      3          |   1.1.1.1.  |      0        |
|      7 | 湖南省教育厅       |      1          |  1.2.       |      3        |
|      8 | 长沙市教育厅       |      7          |  1.2.1.     |      0        |
|      9 | 湘潭市教育厅       |      7          |  1.2.2.     |      0        |
|     10 | 张家界市教育厅     |      7          | 1.2.3.       |      0        |
+--------+-------------------+---------------+--------------+--------------+

改进的前缀编码模型中添加了直系父节点id的parent_id,和当前子节点分配最大数childMaxNum(记录了当前已分配的数字),前缀编码code使用特殊符号区分节点的层次。
查找子孙节点sql:
select * from unit where code like ‘1.1.%’

嵌套集合模型

模型图:
嵌套集合模型图
使用左值和右值来表现嵌套集合模型中数据的分层特性。
优点:
所有子孙节点的左右值都在父节点的左右值范围内,能快速查找出一棵子树,且能快速判断是否含有子节点。
缺点:
1、当增加删除一个节点时,需要更新其他节点的左右值。
2、层级不明显。

二叉树模型

这里写图片描述
把这种层级结构变换为二叉树模型,变换规则,某节点A的左边第一个子节点B作为A左子节点,B右边第一个兄弟节点C作为B的右子节点,如果C右边还有兄弟节点D,则把D作为C的右子节点,如此类推。最后变换为下图:
这里写图片描述
每个节点的编码以一维数组存放二叉树的方式进行编码

+-------------+-----------------+----------+
|          id | name            | location |
+--------+----------------------+----------+
|           1 | Seewo智慧学校     |  1      |
|           2 | 广东省教育厅       |  2      |
|           3 | 广州市教育厅       |  4      |
|           4 | 东莞市教育厅       |  9      |
|           5 | 佛山市教育厅       |  19     |
|           6 | 荔湾区华侨小学     |   8     |
|           7 | 湖南省教育厅       |  5      |
|           8 | 长沙市教育厅       |  10     |
|           9 | 湘潭市教育厅       |  21     |
|         10 | 张家界市教育厅      | 43      |
+-------------+-----------------+---------+

MongoDB实现

使用非关系型数据库优点可以快速的查找

{ id"1",   name:"Seewo智慧学校", ancestors:[],     parent:null }
{ id"2", name:"广东省教育厅",  ancestors:["1"], parent:"1" }
{ id"3", name:"广州市教育厅 ",  ancestors:["1","2"], parent:"2" }
{ id"4", name:"东莞市教育厅",  ancestors:["1","2"], parent:"2" }
{ id"5", name:"佛山市教育厅",  ancestors:["1","2"], parent:"2" }
{ id"6", name:"荔湾区华侨小学",  ancestors:["1","2","3"], parent:"3" }
{ id"7", name:"湖南省教育厅",  ancestors:["1"], parent:"1" }
{ id"8", name:"长沙市教育厅",  ancestors:["1","8"], parent:"7" }
{ id"9", name:"湘潭市教育厅",  ancestors:["1","8"], parent:"7" }
{ id"10", name:"张家界市教育厅",  ancestors:["1","8"], parent:"7" }

查找id=1的所有子孙节点:find({ancestors:”1”})

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值