`
石头的日记
  • 浏览: 200778 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类

一种理想的在关系数据库中存储树型结构数据的方法

阅读更多

一种理想的在关系数据库中存储树型结构数据的方法
2008-06-24 17:05 by Jacky_Xu, 1553 visits, 网摘, 收藏, 编辑
在各种基于关系数据库的应用系统开发中,我们往往需要存储树型结构的数据,目前有很多流行的方法,如邻接列表模型(The Adjacency List Model),在此基础上也有很多人针对不同的需求做了相应的改进,但总是在某些方面存在的各种各样的缺陷。
    那么理想中的树型结构应具备哪些特点呢?数据存储冗余小、直观性强;方便返回整个树型结构数据;可以很轻松的返回某一子树(方便分层加载);快整获以某节 点的祖谱路径;插入、删除、移动节点效率高等等。带着这些需求我查找了很多资料,发现了一种理想的树型结构数据存储及操作算法,改进的前序遍历树模型 (The Nested Set Model)。
一、数据

    在本文中,举一个在线食品店树形图的例子。这个食品店通过类别、颜色和品种来组织食品。树形图如下:


 

二、邻接列表模型(The Adjacency List Model)

在这种模型下,上述数据在关系数据库的表结构数据通常如下图所示:



 
由于该模型比较简单,在此不再详细介绍其算法,下面列出它的一些不足:

    在大多数编程语言中,他运行很慢,效率很差。这主要是“递归”造成的。我们每次查询节点都要访问数据库。每次数据库查询都要花费一些时间,这让函数处理庞 大的树时会十分慢。造成这个函数不是太快的第二个原因可能是你使用的语言。不像Lisp这类语言,大多数语言不是针对递归函数设计的。对于每个节点造成这 个函数不是太快的第二个原因可能是你使用的语言。不像Lisp这类语言,大多数语言不是针对递归函数设计的。对于每个节点,函数都要调用他自己,产生新的 实例。这样,对于一个4层的树,你可能同时要运行4个函数副本。对于每个函数都要占用一块内存并且需要一定的时间初始化,这样处理大树时递归就很慢了。

三、改进的前序遍历树模型(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;

 

 

 

 

以上属于转载

 

这种树形结构与查询有利,但在作节点位置修改时耗费巨大,最差的算法,你得把一棵树的节点序号统统修改个遍,因此凡事有利有弊

 


 

  • 大小: 21.7 KB
  • 大小: 33.3 KB
  • 大小: 40.2 KB
  • 大小: 44.5 KB
分享到:
评论

相关推荐

    Delphi中数据库关联树型结构生成与同步数据维护.zip_数据同步_数据库关联_数据维护_树型结构生成

    树型结构是一种常见的数据表示方式,尤其适合展示层级关系的数据,如组织结构、文件系统等。在Delphi中,TTreeView组件是用于创建和展示树型结构的工具。开发者可以通过填充TTreeNode对象,构建出反映数据库中表和...

    如何展开存储在数据库中的树形数据结构.pdf

    通过对这些方法的了解和应用,开发者可以更加高效地管理和查询存储在数据库中的树形数据结构,从而在实际工作中提升数据处理的能力和效率。同时,这些方法也能够帮助开发者深入理解树形数据结构的特点和遍历算法的...

    易语言数据库填充到树型框例程

    在本例程中,“易语言数据库填充到树型框例程”是关于如何利用易语言将数据库中的数据有效地展示在程序界面的树型控件(树形结构)上的一种实现方式。 首先,我们要理解数据库的基本概念。数据库是存储和管理数据的...

    一种基于Ajax的动态树型结构的设计与实现.pdf

    ### 一种基于Ajax的动态树型结构的设计与实现 #### 摘要 本文提出了一种新型的动态树型结构的实现方案,该方案利用了Yahoo用户界面库和Ajax(异步JavaScript和XML)技术。这种方法能够构建出结构清晰、具有良好...

    教你如何用java开发树型结构

    在Java开发中,树型结构是一种常见的数据组织方式,它模拟了自然界中的树状结构,由节点(Node)和边(Edge)组成,每个节点可以有零个或多个子节点。这种结构在很多场景下都非常有用,比如文件系统、组织架构、...

    递归法读取数据库树型结构示例

    在IT领域,数据库通常用于存储和管理大量有组织的数据,而树型结构是数据库中一种常见且有效的数据表示形式。这种结构模拟了现实世界中事物的层级关系,非常适合用来表示目录、组织架构、文件系统等。本文将深入探讨...

    完整版数据库填充到树型框例程.e.rar

    数据库填充到树型框是软件开发中常见的交互方式,尤其在数据管理或界面展示时,它可以帮助用户以层次结构的方式查看和操作数据。这个“完整版数据库填充到树型框例程.e.rar”可能是一个包含源代码、示例或者教程的...

    完整版数据库填充到树型框例程.rar

    在用户界面设计中,树型框(Tree View)是一种常见的控件,用于显示层次结构的数据。它以节点的形式展现数据,每个节点可以有子节点,形成一个可展开和折叠的层级结构,非常适合展示具有层级关系的数据,如目录结构...

    数据库填充到树型框例程.rar

    树形控件是一种常见的用户界面元素,用于以层次结构的方式显示信息,类似于文件系统的目录结构。下面我们将深入探讨这个主题,包括数据库操作、数据结构化以及树型框的使用。 首先,我们需要理解数据库的基本概念。...

    delphi 树型控件自动根据数据集生成树型结构

    在 Delphi 开发环境中,树型控件(TTreeview)是一种常见的用户界面元素,用于显示层次化的数据。本文将详细讲解如何在 Delphi7 中使用树型控件,并自动根据数据集生成树型结构。 首先,理解 TTreeView 控件的基本...

    使用冗余数据设计树型关系的数据结构.pdf

    树型关系数据结构是一种常见的数据组织形式,尤其是在层次数据库中,它能够有效地表达层次关系。 接下来,我们将详细探讨使用冗余数据设计树型关系数据结构时需要注意的几个关键知识点: 1. 树型数据结构的定义和...

    数据库填充到树型框例程.e.rar

    数据库填充到树型框是一种常见的数据可视化技术,尤其在开发用户界面时,它能帮助用户以层次结构的方式浏览和操作数据。在这个例子中,“数据库填充到树型框例程.e.rar”很可能包含了一个示例程序或者代码片段,用于...

    树型数据结构在测井软件中的应用.pdf

    树型数据结构作为一种重要的非线性数据结构,在信息处理、存储以及搜索操作中具有高效性。因此,在测井软件中应用树型数据结构对于提高测井数据的处理速度和效率具有重要的现实意义。 在描述中提到的“测井数据的...

    JSP实现树型结构TREE

    在IT行业中,构建树型结构的数据展示是一种常见的需求,特别是在Web应用中,用户界面往往需要以层次化的形式展示数据。本例"JSP实现树型结构TREE"提供了一个使用JSP(JavaServer Pages)、EXTJS(一个前端JavaScript...

    树型结构的一个例子

    在IT领域,树型结构是一种常见的数据组织方式,它模拟了自然界中的树状关系,具有根节点、子节点和父节点的概念。在这个特定的Delphi示例程序中,"飘摇客"在2002年创建了一个用递归方法读取数据库数据并构建树形视图...

    winform树型结构

    树型结构(TreeView)是WinForm中常见的一种控件,它用于显示层次化的数据,通常表现为节点和子节点的形式,类似于计算机文件系统的目录结构。对于初学者来说,理解和掌握如何在WinForm中使用树型控件是非常重要的...

    jb+数据库+三级树型菜单

    在描述中提到的“jb+数据库+三级树型菜单”可能指的是使用Java(jb)技术来构建一个数据库驱动的应用,其中包含了一个能够展示三层结构的树型菜单。这个菜单系统可能是为了方便用户在复杂的数据结构中导航,比如在...

    基于JDOM的XML技术用于“树型”数据结构的研究.pdf

    1. 树型数据结构在传统数据库系统中的局限性:在关系数据库中,如果要存储类似树型的数据结构,将需要创建多个二维表来代表各个节点之间的关系,这会导致系统维护复杂度上升,查询效率降低,且在修改如名称等字段时...

    ROOT树型结构(JSP)

    "ROOT树型结构"通常指的是在Web应用中用于组织和展示数据的一种图形化方式,特别是对于层次结构明显的数据,如目录、组织架构或文件系统等。这种结构以树状的形式呈现,用户可以通过展开和折叠节点来探索和操作数据...

    XML技术用于存取“树型”数据结构.pdf

    树型数据结构是一种常用的数据结构,在计算机科学中广泛应用于各种场景,比如文件系统、组织架构、XML文档本身等。本文的作者,王之怡和王卓飞,在项目开发中遇到了需要存取部门、机房和计算机信息的需求,并且这些...

Global site tag (gtag.js) - Google Analytics