PHP+Mysql树型结构(无限分类)数据库设计的2种方
在数据库中保存树状结构数据时,例如分类、菜单或论坛帖子的树状回复等,常见的方法主要有两种:邻接表方式和预排序遍历树方式。这篇文章将介绍这两种方法的实例,并对其优劣进行分析和。
一、邻接表方式
这种方法主要依赖于一个表示父节点的字段,通过连接相邻的上下级节点来构建树状结构。例如,假设我们有一个分类系统,"Java"是"Language"的子节点,那么在数据库中就会有一条记录显示"Java"的父节点是"Language"。
PHP与MySQL结合实现这种方式的代码相对直观。例如,我们可以定义一个函数`show_children`来显示一个节点下的所有子节点。这个函数会递归地查询数据库,获取每个子节点的信息,并缩进显示,以表示其在树结构中的层级。
我们还可以通过一个`get_path`函数来获取从根节点到某个特定节点的路径。这个函数会递归地查询数据库,获取当前节点的父节点信息,直到根节点,然后将路径以数组的形式返回。
邻接表方式的优点是易于理解和实现,代码简单明了。其缺点在于当树状结构较大时,递归查询会导致数据库负载增大,扩展性较差。
二、预排序遍历树方式(MPTT)
预排序遍历树方式是一种更为复杂但效率更高的方法。在MPTT中,每个节点都有两个额外的字段:左值(lft)和右值(rgt),用于表示该节点在树中的位置。通过遍历整个树并更新这些字段的值,我们可以轻松地获取任何节点的子节点、父节点和兄弟节点。
MPTT的优点在于查询效率高,特别是获取某一节点下的所有子节点或查找某个节点的路径时,只需通过简单的SQL查询即可完成,无需递归查询。MPTT的扩展性也更好,可以处理大型的树状结构。
MPTT的缺点在于实现复杂,需要更多的数据库操作来更新节点的左值和右值。由于每个节点的位置信息都存储在数据库中,因此占用的存储空间也会更多。
展示从根节点到某一节点的路径变得异常简单。以获取“ORACLE”这个节点的路径为例,只需要一句SQL查询即可。其左右值分别为7和10,对应的SQL语句为:
```sql
SELECT name FROM tree WHERE lft <= 7 AND rgt >= 10 ORDER BY lft ASC;
```
在PHP中,我们可以通过一个函数轻松地实现这一操作:
```php
function get_path2($node_id) {
// 获取当前节点的左右值
$result = mysql_query('SELECT lft, rgt FROM tree WHERE id='tval($node_id));
$row = mysql_fetch_array($result);
// 获取路径中的所有节点
$result = mysql_query('SELECT name FROM tree WHERE lft <= '.$row['lft'].' AND rgt >= '.$row['rgt'].' ORDER BY lft ASC');
$path = array();
while ($row = mysql_fetch_array($result)) {
$path[] = $row['name'];
}
return $path;
}
```
```sql
UPDATE tree SET rgt=rgt+2 WHERE rgt>9;
UPDATE tree SET lft=lft+2 WHERE lft>9;
```
```sql
INSERT INTO tree SET lft=10, rgt=11, name='ORACLE 10';
```
预排序遍历树方式的优点在于,树的构造和路径获取方面的性能都优于邻接表方式。其缺点也不可忽视。预排序遍历树的算法相对抽象,不易理解。在增加节点时,尽管只需要几条SQL语句,但可能需要更新大量记录,这可能会造成数据库的短暂阻塞。尽管如此,由于其读的性能优势,在WEB应用中,预排序遍历树方式仍然比邻接表方式更受欢迎,更为实用。很多应用中都可以看到MPTT(预排序遍历树)的影子,通常的表里都有字段lft和rgt。
总体而言,预排序遍历树方式是一种牺牲写的性能以换取读的性能的策略。在数据库读取操作远多于写入操作的场景下,这种方式表现出其独特的优势。而随着社会对于数据处理效率的要求越来越高,预排序遍历树方式的应用前景仍然广阔。在编写代码时,可以根据实际需求选择最合适的数据结构处理方式。至于具体的实现代码,需要根据实际的应用环境和需求进行调整和优化。
编程语言
- PHP+Mysql树型结构(无限分类)数据库设计的2种方
- 彻底搞懂PHP 变量结构体
- jQuery控制元素显示、隐藏、切换、滑动的方法总
- Jquery AJAX POST与GET之间的区别详细介绍
- javascript容错处理代码(屏蔽js错误)
- js数组去重的5种算法实现
- 详解Struts2中Action访问Servlet API的几种方法
- ASP.NET中Config文件的读写示例
- smarty模板的使用方法实例分析
- 初探JavaScript 面向对象(推荐)
- jquery对Json的各种遍历方法总结(必看篇)
- 详解vue中的父子传值双向绑定及数据更新问题
- 浅谈PHP调用Webservice思路及源码分享
- sql server deadlock跟踪的4种实现方法
- nodejs body-parser 解析post数据实例
- Javascript编写俄罗斯方块思路及实例