php和mysql处理树状_分级_无限分类_分层数据的方法_PHP和MySQL处理树状、分级、无限分类、分层数据的方法...

news/2024/2/22 17:54:46

文章标题中的多个词语表达的其实是一个意思,就是递归分类数据,分级数据非常类似数据结构中的树状结构,即每个节点有自己的孩子节点,孩子结点本身也是父亲节点。这是一个递归、分层形式。可以称之为树形层级数据。

层级数据结构是编程语言中非常普通的一种数据结构,它代表一系列的数据每一项都有一个父亲节点(除了根节点)和其他多个孩子结点。WEB开发人员使用层级数据结构用于非常多的场景,包括内容管理系统CMS、论坛主题、邮件列表,还有电子商务网站的产品分类等。

本文章主要介绍了使用PHP和MYSQL来管理分级数据的方法,在其中将给出两种最流行的分级数据模型:

邻接表模型

嵌套集合模型

邻接表模型用于分层数据邻接表模型是一种分级数据模型,其中每个节点有一个指向其父亲的指针(根节点该指针为空值),使用下面的SQL语句将建立该结构并插入测试数据:

PHP%E5%A4%84%E7%90%86%E5%B1%82%E7%BA%A7%E5%85%B3%E7%B3%BB.png

parent_id就是它的父节点的ID号,这种方法非常简单,因为能很容易的看清楚父子关系。使用以下的简单PHP函数代码可以很容易的输出树状路径:

function get_path($category_id)

{

$con = mysql_connect("localhost","root","123456");

if (!$con) {

die('数据库连接失败: ' . mysql_error());

}

mysql_select_db('test',$con);

// 查找当前节点的父节点的ID,这里使用表自身与自身连接实现

$sql = "

SELECT c1.parent_id,c2.category_name AS parent_name

FROM category AS c1

LEFT JOIN category AS c2

ON c1.parent_id=c2.category_id

WHERE c1.category_id='$category_id' ";

//echo $sql."
";//测试把SQL打印出来,拿到数据库执行一下看看结果

$result = mysql_query($sql);

$row = mysql_fetch_array($result);//现在$row数组存了父亲节点的ID和名称信息

// 将树状路径保存在数组里面

$path = array();

//如果父亲节点不为空(根节点),就把父节点加到路径里面

if ($row['parent_id']!=NULL)

{

//将父节点信息存入一个数组元素

$parent[0]['category_id'] = $row['parent_id'];

$parent[0]['category_name'] = $row['parent_name'];

//递归的将父节点加到路径中

$path = array_merge(get_path($row['parent_id']),$parent);

}

return $path;

}

//根据上面的图可以看出,K的ID是11,我们就用它来测试路径

$path = get_path(11);

echo "

路径数组:

";

echo "

";

print_r($path);

echo "

";

//将路径到根节点的路径打印出来

//打印结果:J>I>D>A>

echo "

向根节点打印路径:

";

for ($i=count($path)-1; $i>=0; $i--)

{

echo $path[$i]['category_name']. '>';

}

?>

运行结果截图:

QQ%E6%88%AA%E5%9B%BE20120821131648.png

由此可以知道怎样找到一个叶子节点(没有孩子的节点)到根节点的路径,下面来看怎样从根节点往下来遍历层级结构,通过节点的层级关系来打印所有的节点:

该段代码运行结果:

QQ%E6%88%AA%E5%9B%BE20120821132607.png

然而,邻接表模型(每个节点存储父亲节点信息)有它的劣势,首先使用数据库的查询语句很难直接实现它,需要借助PHP代码实现。SQL语句需要你知道节点位于哪一个层级。并且每个树层是使用SQL的自我表连接实现的,这意味着树的每一层处理都会降低数据库的性能。

删除节点的过程也会导致一些问题,如果只删除了某个节点它却有孩子,结果是它的孩子成了孤儿(就是没有父亲了),真正的体现就是,这些孩子节点从树中相当于“消失了”。

嵌套集合模型用于树形分层结构数据嵌套集合模型,也叫做先根遍历树算法,也是一种处理树形层级数据的方法。代替节点间的父子关系,层级使用嵌套的容器的集合来表示,其中每个节点具有两个值,一个left,一个right。以下是例子的模拟图:

PHP%E5%A4%84%E7%90%86%E5%B1%82%E7%BA%A7-%E5%85%88%E5%BA%8F%E9%81%8D%E5%8E%86%E6%A0%91.png

决定left和right的值的过程是从左到右进行的,首先给left赋值,让后向下遍历节点的孩子们,最后才能得到节点的right的值。SQL语句如下所示:

CREATE TABLE category (

category_id INT(10) AUTO_INCREMENT PRIMARY KEY,

category_name VARCHAR(50) NOT NULL,

lft INT(10) NOT NULL,

rgt INT(10) NOT NULL

);

现在可以用一句SQL查询得到整个树的节点:

SELECT * FROM category WHERE lft BETWEEN 1 AND 14 ORDER BY lft ASC

在本SQL中的两个数字值1和14就是根节点的left和right值。类似的如果想得到某个节点的所有孩子节点,只需要将该SQL语句的1和14替换成本节点的left和right值就可以了。例如,如果想得到所有男人的衣服,可以用下面的SQL语句:

SELECT * FROM category WHERE lft BETWEEN 2 AND 7 ORDER BY lft ASC

想找到一条到某个节点的路径,用一条SQL语句就可以搞定:

SELECT * FROM category WHERE lft < 9 AND rgt > 10 ORDER BY lft ASC

请仔细观察一下一些叶子节点到根节点的路径。就会发现所有的祖先都有更小的左值和更大的右值。本例子中一条到裙子分类的路径被取出。观察一下裙子的所有left值都小于9,right值都大于10,其他的非祖先节点都不满足该要求。

尽管嵌套集合模型更加复杂并且有些难以理解,它有非常多的优势。它不需要依赖其他资源(比如PHP代码),也不需要递归。同时,数据库查询语句非常的简单,大多数用一条SQL语句就可以搞定。这些特性都能够显著的增加应用程序的性能,使得它能够用可接受的速度来处理复杂的层级结构。

然而万事皆无完美,更新该层级结构(增加或删除节点)却更加的复杂,并且可能会非常慢。

增加一个节点到层级结构的方法:

将一个节点插入到层级数据中,需要整个树很多节点的left和right值的更新。例如,如果你想将一个男士运动鞋的分类插入到男性衣服的短裤后面。那么所有你必须将大于6的所有left和right值都增加2。为什么呢?因为短裤的right值是6,那你就必须将你的新分类的left和right值设定为7和8,当然,以下两条SQL就可以解决:

UPDATE category SET rgt=rgt+2 WHERE rgt>6

UPDATE category SET lft=lft+2 WHERE lft>6

现在树中间已经有空隙用来插入新分类了,用一条SQL插入该节点:

INSERT INTO category (category_name,lft,rgt) VALUES ('Sneakers','7','8')

树形层级数据中删除一个节点的方法:

在层级集合模型中删除一个节点的方法,比在邻接表中相同的操作稍微难一些。不同的操作的复杂程度是不同的,比如删除一个叶子节点和一个带孩子节点就很不同。

要删除一个叶子节点,先将所有left和right大于该节点left和right值的节点的left和right减去2,然后再删除该节点。以下使用SQL实现该过程:

UPDATE category SET lft=lft-2 WHERE lft>5

UPDATE category SET rgt=rgt-2 WHERE rgt>6

DELETE FROM category WHERE lft='5' AND rgt='6'

该例子中短裤节点被删除了。

如果要删除的节点有孩子节点的话,删除过程会多一个步骤:

比如我们删除男性衣服分类的时候:

UPDATE category SET lft=lft-1,rgt=rgt-1 WHERE lft>2 AND rgt<7

UPDATE category SET lft=lft-2 WHERE lft>7

UPDATE category SET rgt=rgt-2 WHERE rgt>7

DELETE FROM category WHERE lft='2' AND rgt='7'

哪种模型对于处理树形分层数据更好?哪种情况更好呢,看情况。如果需要一个更加灵活的模型,更容易更新,就用邻接表模型吧。如果分类构成了一棵复杂的数,并且更新不需要很频繁,用嵌套集合模型肯定是上上之选。

本文内容翻译自:访问,其中原文中的代码有些问题,本人添加了测试数据并改正了代码。


https://dhexx.cn/news/show-16892.html

相关文章

PS长图快速切片_PS最常用的100多个快捷键

PS最常用的100多个快捷键这些快捷键都是比较常用的&#xff0c;一些比较生僻的快捷键我就不发出来了。这些快捷键大家可以抄下来&#xff0c;但是&#xff0c;完全没有必要刻意的想去记住它&#xff0c;因为你越是想刻意的记住它&#xff0c;越是记不住。下面这一百多个快捷键全…

UVa 294 (因数的个数) Divisors

题意&#xff1a; 求区间[L, U]的正因数的个数。 分析&#xff1a; 有这样一条公式&#xff0c;将n分解为&#xff0c;则n的正因数的个数为 事先打好素数表&#xff0c;按照上面的公式统计出最大值即可。 1 #include <cstdio>2 #include <cmath>3 4 const int maxn…

uft自动化测试工具安装步骤_2020年十大最佳自动化测试工具

Best Automation Testing Tools for 2020对更快交付高质量软件(或"快速质量")的需求要求组织以敏捷&#xff0c;持续集成(CI)和DevOps方法论来寻找解决方案。测试自动化是这些方面的重要组成部分。最新的《 2018-2019年世界质量报告》表明&#xff0c;测试自动化是实…

hive 取消打印日志信息_Hive为什么这么受欢迎?来看Hive架构以及应用介绍

Hive究竟是什么&#xff0c;为什么在Hadoop家族中占有这么重要的地位&#xff0c;本篇文章将围绕Hive的体系结构(架构)、Hive的操作、Hive与Hbase的区别等对Hive进行全方面的阐述。作者&#xff1a;Python工程师Hive这个框架在Hadoop的生态体系结构中占有及其重要的地位&#x…

【百度地图API】如何批量转换为百度经纬度

【百度地图API】如何批量转换为百度经纬度 原文:【百度地图API】如何批量转换为百度经纬度摘要&#xff1a; 百度地图API的官网上提供了常用坐标转换的示例。但是&#xff0c;一次只能转换一个&#xff0c;真的非常麻烦&#xff01;&#xff01;这里结合了官方的示例&#xff0…

getprocaddress得到为0_TensorFlow从0到1 - 15 - 重新思考神经网络初始化

上一篇14 交叉熵损失函数——克服学习缓慢从最优化算法层面入手&#xff0c;将二次的均方误差&#xff08;MSE&#xff09;更换为交叉熵作为损失函数&#xff0c;避免了当出现“严重错误”时导致的学习缓慢。本篇引入1/sqrt(nin)权重初始化方法&#xff0c;从另一个层面——参数…

类的组合在什么情况下使用_什么情况下使用切片防草布?切片防草布都有什么规格呢...

防草布(园艺地布)是整卷的布状物&#xff0c;通常幅宽为0.5--2米&#xff0c;卷长为100米--800米&#xff0c;在使用时只需要将防草布展开平铺即可。但是有些情况之下不适合使用整卷的防草布&#xff0c;而人工裁剪费时费力对原材料(防草布)还有很大的损耗&#xff0c;自己剪裁…

python seaborn_【Python可视化3】Seaborn之箱线图与小提琴图

Seaborn是基于matplotlib的Python可视化库。它提供了一个高级界面来绘制有吸引力的统计图形。Seaborn其实是在matplotlib的基础上进行了更高级的API封装&#xff0c;从而使得作图更加容易&#xff0c;不需要经过大量的调整就能使你的图变得精致。但应强调的是&#xff0c;应该把…

python二维图颜色函数_Python绘图之二维图与三维图详解

各位工程师累了吗? 推荐一篇可以让你技术能力达到出神入化的网站"持久男" 1.二维绘图 a. 一维数据集 用 Numpy ndarray 作为数据传入 ply 1. import numpy as np import matplotlib as mpl import matplotlib.pyplot as plt np.random.seed(1000) y np.random.stan…

大熊君大话NodeJS之------MongoDB模块(额外篇)

一&#xff0c;开篇分析 这篇属于扩展知识篇&#xff0c;因为在下面的文章中会用到数据库操作&#xff0c;所以今天就来说说它&#xff08;Mongodb模块&#xff09;。 &#xff08;1&#xff09;&#xff0c;简介 MongoDB是一个基于分布式文件存储的数据库。由C语言编写。旨在为…