树在mysql的存法_在关系数据库中存储树型结构数据的方法

本文介绍了改进的前序遍历树模型(Nested Set Model)的原理,通过左值和右值来存储树结构。利用SQL语句展示了如何实现返回完整树、子树、节点路径、节点深度以及叶子节点等操作。同时,还演示了如何插入和删除节点。
摘要由CSDN通过智能技术生成

改进的前序遍历树模型(The Nested Set Model)

原理:

我们先把树按照水平方式摆开。从根节点开始(“Food”),然后他的左边写上1。然后按照树的顺序(从上到下)给“Fruit”的左边写上2。这样,你沿着树的边界走啊走(这就是“遍历”),然后同时在每个节点的左边和右边写上数字。最后,我们回到了根节点“Food”在右边写上18。下面是标上了数字的树,同时把遍历的顺序用箭头标出来了。

3021038586772a9f70cde85ecc863151.png

我们称这些数字为左值和右值(如,“Food”的左值是1,右值是18)。正如你所见,这些数字按时了每个节点之间的关系。因为“Red”有3和6两个值,所以,它是有拥有1-18值的“Food”节点的后续。同样的,我们可以推断所有左值大于2并且右值小于11的节点,都是有2-11的“Fruit” 节点的后续。这样,树的结构就通过左值和右值储存下来了。这种数遍整棵树算节点的方法叫做“改进前序遍历树”算法。

表结构设计:

de505240a291daf0a66d9b0e9c795198.png

常用的操作:

下面列出一些常用操作的SQL语句

返回完整的树(Retrieving a Full Tree)

SELECTnode.nameFROMnested_category node, nested_category parentWHEREnode.lftBETWEENparent.lftANDparent.rgtANDparent.name='electronics'ORDERBYnode.lft

返回某结点的子树(Find the Immediate Subordinates of a Node)

SELECTV.*FROM(SELECTnode.name,

(COUNT(parent.name)-(AVG(sub_tree.depth)+1)) depthFROMnested_category node,

nested_category parent,

nested_category sub_parent,

(SELECTV.*FROM(SELECTnode.name, (COUNT(parent.name)-1) depthFROMnested_category node, nested_category parentWHEREnode.lftBETWEENparent.lftANDparent.rgtANDnode.name='portable electronics'GROUPBYnode.name) V,

nested_category TWHEREV.name=T.nameORDERBYT.lft) sub_treeWHEREnode.lftBETWEENparent.lftANDparent.rgtANDnode.lftBETWEENsub_parent.lftANDsub_parent.rgtANDsub_parent.name=sub_tree.nameGROUPBYnode.name) V,

nested_category TWHEREV.name=T.nameandV.depth<=1andV.depth>0ORDERBYT.Lft

返回某结点的祖谱路径(Retrieving a Single Path)

SELECTparent.nameFROMnested_category node, nested_category parentWHEREnode.lftBETWEENparent.lftANDparent.rgtANDnode.name='flash'ORDERBYnode.lft

返回所有节点的深度(Finding the Depth of the Nodes)

SELECTV.*FROM(SELECTnode.name, (COUNT(parent.name)-1) depthFROMnested_category node, nested_category parentWHEREnode.lftBETWEENparent.lftANDparent.rgtGROUPBYnode.name) V,

nested_category TWHEREV.name=T.nameORDERBYT.Lft

返回子树的深度(Depth of a Sub-Tree)

SELECTV.*FROM(SELECTnode.name,

(COUNT(parent.name)-(AVG(sub_tree.depth)+1)) depthFROMnested_category node,

nested_category parent,

nested_category sub_parent,

(SELECTV.*FROM(SELECTnode.name, (COUNT(parent.name)-1) depthFROMnested_category node, nested_category parentWHEREnode.lftBETWEENparent.lftANDparent.rgtANDnode.name='portable electronics'GROUPBYnode.name) V,

nested_category TWHEREV.name=T.nameORDERBYT.lft) sub_treeWHEREnode.lftBETWEENparent.lftANDparent.rgtANDnode.lftBETWEENsub_parent.lftANDsub_parent.rgtANDsub_parent.name=sub_tree.nameGROUPBYnode.name) V,

nested_category TWHEREV.name=T.nameORDERBYT.Lft

返回所有的叶子节点(Finding all the Leaf Nodes)

SELECTnameFROMnested_categoryWHERErgt=lft+1

插入节点(Adding New Nodes)

LOCKTABLEnested_category WRITE;SELECT@myRight:=rgtFROMnested_categoryWHEREname='TELEVISIONS';UPDATEnested_categorySETrgt=rgt+2WHERErgt>@myRight;UPDATEnested_categorySETlft=lft+2WHERElft>@myRight;INSERTINTOnested_category

(name, lft, rgt)VALUES('GAME CONSOLES',@myRight+1,@myRight+2);

UNLOCK TABLES;

删除节点(Deleting Nodes)

LOCKTABLEnested_category WRITE;SELECT@myLeft:=lft,@myRight:=rgt,@myWidth:=rgt-lft+1FROMnested_categoryWHEREname='GAME CONSOLES';DELETEFROMnested_categoryWHERElftBETWEEN@myLeftAND@myRight;UPDATEnested_categorySETrgt=rgt-@myWidthWHERErgt>@myRight;UPDATEnested_categorySETlft=lft-@myWidthWHERElft>@myRight;

UNLOCK TABLES;

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2010-02-05 16:27

浏览 2058

评论

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值