当前位置:  编程技术>php

PHP+Mysql树型结构(无限分类)数据库设计的2种方式实例

    来源: 互联网  发布时间:2014-08-26

    本文导语:  我们经常需要在关系型数据库中保存一些树状结构数据,比如分类、菜单、论坛帖子树状回复等。常用的方法有两种: 1. 领接表的方式; 2. 预排序遍历树方式; 假设树状结构如下图: 领接表方式 主要依赖于一个 parent 字段...

我们经常需要在关系型数据库中保存一些树状结构数据,比如分类、菜单、论坛帖子树状回复等。常用的方法有两种:

1. 领接表的方式;

2. 预排序遍历树方式;

假设树状结构如下图:

领接表方式

主要依赖于一个 parent 字段,用于指向上级节点,将相邻的上下级节点连接起来,id 为自动递增自动,parent_id 为上级节点的 id。一目了然,“Java”是“Language”的子节点。

我们要显示树,PHP 代码也可以很直观,代码如下:

代码如下:


想要显示整个树结构,调用 show_children()。想要显示“Database”子树,则调用 show_children(2),因为“Database”的 id 是 2。

还有一个经常用到的功能是获取节点路径,即给出一个节点,返回从根节点到当前节点的路径。用函数实现如下:

代码如下:


想要获取“MySQL 5.0”的路径,调用 get_path(4),4 即是这个节点的 id。

领接表方式的优点在于容易理解,代码也比较简单明了。缺点则是递归中的 SQL 查询会导致负载变大,特别是需要处理比较大型的树状结构的时候,查询语句会随着层级的增加而增加,WEB 应用的瓶颈基本都在数据库方面,所以这是一个比较致命的缺点,直接导致树结构的扩展困难重重。

排序遍历树方式

现在我们来聊聊第二种方式─预排序遍历树方式(即通常所说的 MPTT,Modified Preorder Tree Traversal)。此算法是在第一种方式的基础之上,给每个节点增加一个左、右数字,用于标识节点的遍历顺序,如下图所示:

从根节点开始左边为 1,然后下一个节点的左边为 2,以此类推,到最低层节点之后,最低层节点的右边为其左边的数字加 1。顺着这些节点,我们可以很容易地遍历完整个树。根据上图,我们对数据表做一些改变,增加两个字段,lft 和 rgt 用于存储左右数字(由于 left 和 right 是 MySQL 的保留字,所以我们改用简写)。表中各行的内容也就变成了:

接下来看看显示树/子树是多么简单,只需要一条 SQL 语句即可,比如显示“Database”子树,则需要获取到“Database”的左右数字,左为 2,右为 11,那么 SQL 语句是:

代码如下:

SELECT * FROM tree WHERE lft BETWEEN 2 AND 11;

SQL 语句是简单了,但我们所希望的缩进显示却是个问题。什么时候应该显示缩进?缩进多少单位?解决这个问题,需要使用堆栈,即后进先出(LIFO),每到一个节点,将其右边的数字压入堆栈中。我们知道,所有节点右边的值都比其父节点右边的值小,那么将当前节点右边的值和堆栈最上边的右边值进行比较,如果当前节点比堆栈最上边的值小,表示当前堆栈里边剩下的都是父节点了,这时可以显示缩进,堆栈的元素数量即是缩进深度。PHP 代码实现如下:

代码如下:



获取整个树调用 show_tree(),获取“Database”子树调用show_tree(2)。在这个函数中,我们总算不需要用到递归了,呵呵。

接下来是显示从根节点到某节点的路径,这比起领接表方式来说也简单了很多,只需要一句 SQL 就行,不用递归  比如获取“ORACLE”这个节点的路径,其左右值分别是 7 和 10,则 SQL 语句为:

代码如下:

SELECT name FROM tree WHERE lft = 10 ORDER BY lft ASC;

PHP 函数实现如下:

代码如下:


显示树和路径都没问题了,现在需要了解一下如何插入一个节点。插入新节点之前,首先要给这个节点腾出空位来,假设我们现在要在“ORACLE 9i”这个节点右边增加一个“ORACLE 10”,则腾位的 SQL 语句如下(“ORACLE 9i”的右边值为 9):

代码如下:

UPDATE tree SET rgt=rgt+2 WHERE rgt>9;
UPDATE tree SET lft=lft+2 WHERE lft>9;

位置空出来了,开始插入新节点吧:

代码如下:

INSERT INTO tree SET lft=10, rgt=11, name='ORACLE 10';

调用 show_tree() 看看结果对不对  具体的 PHP 实现代码这里就不写了。

现在总结一下预排序遍历树方式的优缺点。缺点是算法比较抽象,不容易理解,增加节点的时候虽然只用了几条 SQL 语句,但可能会需要更新很多记录,从而造成阻塞。优点是树的构造,路径获取方面性能都比领接表方式好很多。也就是说,这个算法牺牲了一些写的性能来换取读的性能,在 WEB 应用中,读数据库的比例远大于写数据库的比例,所以预排序遍历树方式比领接表方式更加受欢迎,更加实用,很多应用中都能看到 MPTT 的影子,通常所用的表里都有字段 lft 和 rgt。


    
 
 

您可能感兴趣的文章:

  • php session_id()函数介绍及代码实例
  • php 小数点取法实例总结
  • php生成透明背景图片实例
  • php防止sql注入代码实例
  • php逐字拆分字符串 php字符串拆分实例
  • php解析json数据实例
  • php定界符<<<使用技巧和实例
  • php读取sqlite数据库入门实例
  • PHP文件锁定写入实例解析
  • php读取mysql数据库入门实例
  • php生成excel列序号代码实例
  • PHP三元运算的2种写法代码实例
  • PHP接收二进制流并生成文件(实例)
  • php读取mysql入门实例
  • php根据身份证号码计算年龄的实例代码
  • PHP递归函数返回值使用实例
  • php实例分享之html转为rtf格式
  • php文件锁定写入实例教程
  • PHP创建桌面快捷方式的实例代码
  • php 强制下载文件实例代码
  • php mailto配置实例
  • PHP学习笔记(二) 了解PHP的基本语法以及目录结构
  • 请问在B/S结构的软件中,浏览器中报表的打印和预览有没有什么好的解决方案?我用的是PHP和JSP!
  • PHP循环结构实例讲解
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • php中内置的mysql数据库连接驱动mysqlnd简介及mysqlnd的配置安装方式
  • 我已经用源代码方式安装了apache,如何让它支持php和mysql(php没有安装,mysql安装的是rpm包),要不要重新安装apache?如何删除已有的ap
  • 命令方式下执行php 可以用类吗?
  • PHP创建桌面快捷方式实现代码
  • php将字符串转化成date存入数据库的两种方式
  • php或asp创建网页桌面快捷方式
  • PHP函数分享之curl方式取得数据、模拟登陆、POST数据
  • PHP获取远程网页内容(fopen,curl方式)
  • PHP URL参数获取方式的四种例子
  • php读取sqlite数据库入门实例 iis7站长之家
  • ASP和PHP实现生成网站快捷方式并下载到桌面的方法
  • PHP命令行脚本接收传入参数的三种方式
  • PHP异步执行常用方式举例
  • PHP页面跳转代码的三种实现方式
  • PHP 页面跳转的六种方式
  • PHP异步调用实现方式详解
  • PHP合并两个数组的两种方式
  • 浅析PHP微信支付通知的处理方式
  • PHP微信支付通知处理方式实现方法
  • PHP以mysqli方式连接类完整代码实例
  • php以mysqli方式连接数据库的类(完整代码)
  • 修改配置真正解决php文件上传大小限制问题(nginx+php)
  • IIS7配置PHP图解(IIS7+PHP_5.2.17/PHP_5.3.5)
  • PHP 5.4.19 和 PHP 5.5.3 发布及下载地址
  • php输入流php://input使用示例(php发送图片流到服务器)
  • 修改配置真正解决php文件上传大小限制问题(apache+php)
  • PHP转换器 HipHop for PHP
  • PHP去除html标签,php标记及css样式代码参考
  • PHP 框架 Pop php
  • PHP 'ext/soap/php_xml.c'不完整修复存在多个任意文件泄露漏洞
  • PHP的JavaScript框架 PHP.JS


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3