树状数据结构存储方式(CUD 篇)-php教程

资源魔 32 0
前文简略引见了嵌套荟萃的数据模子,和查问的办法,传送门: 树状数据构造存储形式 (查问篇)

Create

正在嵌套荟萃模子中,每一个数据其实就是一个节点 (node),而每一个节点占用 2 个位值,比方咱们先新增一个 Smartphones 一级节点开端。

INSERT INTO `categories` (`title`, `lft`, `rgt`) VALUES('Smartphones', 1, 2);

Smartphones 作为一个主节点 (root),它的 lft 必然为 1,而 rgt 的值,会跟着其荟萃内的子元素添加而添加。

如今,咱们心愿正在 Smartphones 内,增加一个子元素 Android。借助 mysql 的存储进程。

LOCK TABLE categories WRITE;
SELECT @root_left := lft FROM categories WHERE title = 'Smartphones';
UPDATE categories SET rgt = rgt + 2 WHERE rgt > @root_left;
UPDATE categories SET lft = lft + 2 WHERE lft > @root_left;
INSERT INTO categories (title, lft, rgt) VALUES('Android', @root_left + 1, @root_left + 2);
UNLOCK TABLES;
SELECT `title`, `lft`, `rgt` FROM `categories`;
+-------------+-----+-----+
| title       | lft | rgt |
+-------------+-----+-----+
| Smartphones |   1 |   4 |
| Android     |   2 |   3 |
+-------------+-----+-----+

咱们再测验考试往 Android 内增加一个子元素 小米:

LOCK TABLE categories WRITE;
SELECT @root_left := lft FROM categories WHERE title = 'Android';
UPDATE categories SET rgt = rgt + 2 WHERE rgt > @root_left;
UPDATE categories SET lft = lft + 2 WHERE lft > @root_left;
INSERT INTO categories (title, lft, rgt) VALUES('小米', @root_left + 1, @root_left + 2);
UNLOCK TABLES;
SELECT `title`, `lft`, `rgt` FROM `categories`;
+-------------+-----+-----+
| title       | lft | rgt |
+-------------+-----+-----+
| Smartphones |   1 |   6 |
| Android     |   2 |   5 |
| 小米        |   3 |   4 |
+-------------+-----+-----+

这时候候,咱们再测验考试往 Smartphones 内增加一个子元素 iOS,正在后面,咱们曾经正在外面增加了一个 Android 元素,以是这里要调整一下存储进程,将 iOS 拔出到 Android 的左边

LOCK TABLE categories WRITE;
SELECT @next_right := rgt FROM categories WHERE title = 'Android';
UPDATE categories SET rgt = rgt + 2 WHERE rgt > @next_right;
UPDATE categories SET lft = lft + 2 WHERE lft > @next_right;
INSERT INTO categories(title, lft, rgt) VALUES('iOS', @next_right + 1, @next_right + 2);
UNLOCK TABLES;
SELECT `title`, `lft`, `rgt` FROM `categories`;
+-------------+-----+-----+
| title       | lft | rgt |
+-------------+-----+-----+
| Smartphones |   1 |   8 |
| Android     |   2 |   5 |
| 小米        |   3 |   4 |
| iOS         |   6 |   7 |
+-------------+-----+-----+

Delete

删除了节点时,其实能够看作是新增节点的逆进程,咱们引入一个宽度,来权衡节点的宽段,其示意为: rgt - lft + 1 以是咱们能够这样写存储进程:

LOCK TABLE categories WRITE;
SELECT @delete_left := lft, @delete_right := rgt, @delete_width := rgt - lft + 1
FROM categories WHERE title = 'Android';
DELETE FROM categories WHERE lft BETWEEN @delete_left AND @delete_right;
UPDATE categories SET rgt = rgt - @delete_width WHERE rgt > @delete_right;
UPDATE categories SET lft = lft - @delete_width WHERE lft > @delete_right;
UNLOCK TABLES;
SELECT `title`, `lft`, `rgt` FROM `categories`;
+-------------+-----+-----+
| title       | lft | rgt |
+-------------+-----+-----+
| Smartphones |   1 |   4 |
| iOS         |   2 |   3 |
+-------------+-----+-----+

Update

挪动节点,是一个比拟复杂的进程,例以下图,macOS 应该归类到 Unix 分类下。

fc14dd8f813809ac120a70439c95871.png

要完成节点的挪动,需求三步:

一、将要挪动的节点摘进去

二、从新编排 lft 以及 rgt 参数

三、将节点挪动到指定地位

LOCK TABLE categories WRITE;
-- 将要挪动的节点摘进去,而且从新边篇 lft 以及 rgt
SELECT @move_left := lft , @move_right := rgt, @move_width := rgt - lft + 1
FROM categories WHERE title = 'macOS';
UPDATE categories SET rgt = -rgt WHERE lft BETWEEN @move_left AND @move_right;
UPDATE categories SET lft = -lft WHERE lft BETWEEN @move_left AND @move_right;
UPDATE categories SET rgt = rgt - @move_width WHERE rgt > @move_right;
UPDATE categories SET lft = lft - @move_width WHERE lft > @move_right;
-- 将节点放到 Unix 节点里
SELECT @root_left := lft FROM categories WHERE title = 'Unix';
UPDATE categories SET rgt = rgt + @move_width WHERE rgt > @root_left;
UPDATE categories SET lft = lft + @move_width WHERE lft > @root_left;
-- 
UPDATE categories SET lft = @root_left + 1 WHERE lft BETWEEN -@move_right AND -@move_left;
UPDATE categories SET rgt = @root_left + 2 WHERE rgt BETWEEN -@move_right AND -@move_left;
UNLOCK TABLES;

总结

其实 SQL 中的嵌套荟萃的数据模子曾经提出很久了,也有不少包曾经完成了这个性能,比方 laravel-nestedset 或许 django-mptt

关于消费应用中,一定是不这么简略的表构造设计,或许乃至此外优化,比方一种称为闭合表的数据模子,这个应该会正在本系列文章中引见给各人。

以上就是树状数据构造存储形式(CUD 篇)的具体内容,更多请存眷资源魔其它相干文章!

标签: php开发教程 php开发资料 php开发自学 数据结构

抱歉,评论功能暂时关闭!