`

The Nested Set Model

阅读更多

原理:

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

 

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

表结构设计:

 

常用的操作:

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

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

SELECT node.name
  FROM nested_category node, nested_category parent
 WHERE node.lft BETWEEN parent.lft AND parent.rgt
   AND parent.name = 'electronics'
 ORDER BY node.lft


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

SELECT V.*
  FROM (SELECT node.name,
               (COUNT(parent.name) - (AVG(sub_tree.depth) + 1)) depth
          FROM nested_category node,
               nested_category parent,
               nested_category sub_parent,
               (SELECT V.*
                  FROM (SELECT node.name, (COUNT(parent.name) - 1) depth
                          FROM nested_category node, nested_category parent
                         WHERE node.lft BETWEEN parent.lft AND parent.rgt
                           AND node.name = 'portable electronics'
                         GROUP BY node.name) V,
                       nested_category T
                 WHERE V.name = T.name
                 ORDER BY T.lft) sub_tree
         WHERE node.lft BETWEEN parent.lft AND parent.rgt
           AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
           AND sub_parent.name = sub_tree.name
         GROUP BY node.name) V,
       nested_category T
 WHERE V.name = T.name
   and V.depth <= 1
   and V.depth > 0
 ORDER BY T.Lft


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

SELECT parent.name
  FROM nested_category node, nested_category parent
 WHERE node.lft BETWEEN parent.lft AND parent.rgt
   AND node.name = 'flash'
 ORDER BY node.lft


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

SELECT V.*
  FROM (SELECT node.name, (COUNT(parent.name) - 1) depth
          FROM nested_category node, nested_category parent
         WHERE node.lft BETWEEN parent.lft AND parent.rgt
         GROUP BY node.name) V,
       nested_category T
 WHERE V.name = T.name
 ORDER BY T.Lft


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

SELECT V.*
  FROM (SELECT node.name,
               (COUNT(parent.name) - (AVG(sub_tree.depth) + 1)) depth
          FROM nested_category node,
               nested_category parent,
               nested_category sub_parent,
               (SELECT V.*
                  FROM (SELECT node.name, (COUNT(parent.name) - 1) depth
                          FROM nested_category node, nested_category parent
                         WHERE node.lft BETWEEN parent.lft AND parent.rgt
                           AND node.name = 'portable electronics'
                         GROUP BY node.name) V,
                       nested_category T
                 WHERE V.name = T.name
                 ORDER BY T.lft) sub_tree
         WHERE node.lft BETWEEN parent.lft AND parent.rgt
           AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt
           AND sub_parent.name = sub_tree.name
         GROUP BY node.name) V,
       nested_category T
 WHERE V.name = T.name
 ORDER BY T.Lft


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

SELECT name FROM nested_category WHERE rgt = lft + 1


插入节点(Adding New Nodes)

LOCK TABLE nested_category WRITE;

SELECT @myRight := rgt FROM nested_category WHERE name = 'TELEVISIONS';

UPDATE nested_category SET rgt = rgt + 2 WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft + 2 WHERE lft > @myRight;

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

UNLOCK TABLES;


删除节点(Deleting Nodes)

LOCK TABLE nested_category WRITE;

SELECT @myLeft := lft, @myRight := rgt, @myWidth := rgt - lft + 1
  FROM nested_category
 WHERE name = 'GAME CONSOLES';

DELETE FROM nested_category WHERE lft BETWEEN @myLeft AND @myRight;

UPDATE nested_category SET rgt = rgt - @myWidth WHERE rgt > @myRight;
UPDATE nested_category SET lft = lft - @myWidth WHERE lft > @myRight;

UNLOCK TABLES;

分享到:
评论
1 楼 liuqq 2011-12-08  
一直用Oracle开发,几乎没有接触过其他数据库。使用Mysql后的确对树的处理变得非常困难。
楼主的文章不错。
但是这个SQL语句没有优化,比如指定深度查询子树这个,我调整了下:
我这里的title等同原SQL的name字段。
/*查询下级节点的同辈元素*/
SELECT V.*
  FROM (SELECT node.title, node.parent,node.lft,
               (COUNT(parent.title) - (AVG(sub_tree.depth) + 1)) depth
          FROM nested_category node,
               nested_category parent,
               (SELECT node.title, (COUNT(parent.title) - 1) depth, node.lft, node.rgt
                          FROM nested_category node, nested_category parent
                         WHERE node.lft BETWEEN parent.lft AND parent.rgt
                           AND node.title = 'Food'
                         GROUP BY node.title) sub_tree
         WHERE node.lft BETWEEN parent.lft AND parent.rgt
           AND node.lft BETWEEN sub_tree.lft AND sub_tree.rgt
         GROUP BY node.title) V
WHERE /* 树的深度*/
V.depth <= 9
   and V.depth >= 0
ORDER BY V.lft

相关推荐

    Laravel开发-laravel-nestedset

    Laravel Nestedset库,如`laravel-nestedset`,是专门为Laravel设计的一个实现嵌套集模型的包。这个包通常由`DaveJamesMiller`维护,它为Laravel提供了处理层级数据的强大工具。 ### 1. 安装与配置 安装`laravel-...

    Laravel开发-nestedset

    在本文中,我们将深入探讨`Laravel开发-nestedset`这一主题,特别是在Laravel 4和5框架中的应用。Nested Set(嵌套集)是一种在关系数据库中存储层级数据的有效方法,尤其适用于需要频繁进行增删改查操作的树形结构...

    go-nested-set:go-nested-set是用于GORM的嵌套集模型的Golang实现

    安装 go get github.com/griffinqiu/go-nested-set用法定义模型您必须使用nestedset Stuct标记来定义Gorm模型,如下所示: 支持结构标签: id -int64-节点的主键parent_id -sql.NullInt64-ParentID列,null为根lft...

    关系数据库存储树形结构数据的理想实践

    在关系数据库中,存储树形结构数据有多种方式,其中主流的方法是使用邻接列表模型(The Adjacency List Model)和嵌套集合模型(The Nested Set Model)。 邻接列表模型是最简单、最直接的存储方式。在邻接列表模型中,...

    Laravel开发-laravel-nested

    "laravel-nested"很可能是一个用于在Laravel中实现嵌套集合(Nested Set)模型的库或者教程。嵌套集合是一种常用的数据结构,特别适合表示具有层级关系的数据,比如目录结构、组织架构等。 在Laravel中,我们通常...

    phpNestedSet-开源

    8. **class.nestedset.php**:核心的 Nested Set 类,封装了与 Nested Set 模型相关的各种操作,如遍历、移动节点、计算深度等。 9. **_getConfig.php**:获取配置参数的函数,可能用于动态读取配置文件。 10. **...

    jqGrid 离线帮助手册

    Nested Set Model Adjacency Model HOWTO Importing and Exporting Methods HOWTO User Modules Show/Hide Columns Table to jqGrid Post Data module HOWTO jQuery UI Integrations Introduction Solutions

    jqGrid 离线帮助手册 来源官方wiki

    Nested Set Model Adjacency Model HOWTO Importing and Exporting Methods HOWTO User Modules Show/Hide Columns Table to jqGrid Post Data module HOWTO jQuery UI Integrations Introduction Solutions

    Laravel开发-nestedsets

    接着,创建一个继承自 `Laraveld\Nestedset\Node` 的模型,如 `Category`: ```php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Laravel\Nestedset\Node; class Category extends Node {...

    Laravel开发-tree

    composer require nestedset/laravel-tree ``` 安装完成后,你需要创建一个模型并继承自 `\Rap2hpoutre\LaravelTree\Eloquent` 或 `\Rap2hpoutre\LaravelTree\Node` 类。这个基类提供了处理嵌套集所需的所有方法,如...

    laravel框架使用DEMO

    Laravel是一款基于PHP的开源Web应用框架,它遵循MVC(Model-View-Controller)架构模式,旨在提供简洁、优雅的工具,帮助开发者创建高质量的Web应用程序。Laravel框架以其丰富的功能、强大的路由系统、易读的代码库...

    Laravel开发-nestedcategories

    安装完成后,你需要创建一个新的Eloquent模型来代表你的类别,继承自`Spatie\NestedSet\Node`模型,例如创建一个`Category`模型: ```php use Spatie\NestedSet\Node; class Category extends Node { // ... } ``...

    nested_sets:PHP 类嵌套集

    嵌套集(Nested Sets)是一种在关系数据库中存储树形结构数据的方法,它提供了一种高效的方式来查询和操作树状数据。PHP 作为一款广泛使用的服务器端脚本语言,经常被用于开发各种Web应用程序,包括那些需要处理树形...

    实现PHP+Mysql无限分类的方法汇总_.docx

    而如果数据量大,且对查询性能有较高要求,Nested Set Model可能更为优选。 为了进一步优化性能,可以考虑使用缓存技术,如Redis或Memcached,将构建好的分类树存储在内存中,减少对数据库的依赖。同时,确保在数据...

    mysql_note_database_

    例如,Nested Set Model是一种有效的方式,通过左值(left)和右值(right)来定义节点的子集。插入、删除和遍历树的操作都需要精心设计的SQL语句。例如,利用`UNION ALL`和递归查询可以实现层次结构的遍历。 总的...

    tp5的nestedsets,方便的对树形结构的数据在关系型数据库中进行管理和操作。.zip

    2. **选择扩展库**:TP5社区提供了很多扩展库,如`Tree`或` NestedSet`,它们为操作Nested Sets提供便捷的方法。这些库通常包括添加、删除、移动节点以及遍历树等功能。 3. **安装和配置**:在你的项目中安装选定的...

    ANSYS Fluent嵌套网格介绍及视频

    在ANSYS Fluent中,嵌套网格(Nested Grids)是一种高级的网格技术,它允许在一个计算域内使用多个不同分辨率的网格,以精细化地模拟特定区域的细节,同时保持整个域的大规模计算效率。这种技术在处理复杂流动问题时...

    Laravel开发-baum

    接着,在相应的 Eloquent 模型中使用 `Baum\NestedSet` trait,并定义好 `left`, `right`, `parent_id`(可选)等字段。 例如,创建一个 `Category` 模型,你可能这样设置: ```php use Baum\NestedSet; class ...

Global site tag (gtag.js) - Google Analytics