溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

樹(shù)狀數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)方式的案例

發(fā)布時(shí)間:2020-11-09 11:51:21 來(lái)源:億速云 閱讀:213 作者:小新 欄目:編程語(yǔ)言

這篇文章主要介紹樹(shù)狀數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)方式的案例,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

Create

在嵌套集合模型中,每個(gè)數(shù)據(jù)其實(shí)就是一個(gè)節(jié)點(diǎn) (node),而每個(gè)節(jié)點(diǎn)占用 2 個(gè)位值,比如我們先新增一個(gè) Smartphones 一級(jí)節(jié)點(diǎn)開(kāi)始。

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

Smartphones 作為一個(gè)主節(jié)點(diǎn) (root),它的 lft 必定為 1,而 rgt 的值,會(huì)隨著其集合內(nèi)的子元素增加而增加。

現(xiàn)在,我們希望在 Smartphones 內(nèi),添加一個(gè)子元素 Android。借助 mysql 的存儲(chǔ)過(guò)程。

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 |
+-------------+-----+-----+

我們?cè)賴L試往 Android 內(nèi)添加一個(gè)子元素 小米:

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 |
+-------------+-----+-----+

這時(shí)候,我們?cè)賴L試往 Smartphones 內(nèi)添加一個(gè)子元素 iOS,在前面,我們已經(jīng)在里面添加了一個(gè) Android 元素,所以這里要調(diào)整一下存儲(chǔ)過(guò)程,將 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

刪除節(jié)點(diǎn)時(shí),其實(shí)可以看做是新增節(jié)點(diǎn)的逆過(guò)程,我們引入一個(gè)寬度,來(lái)衡量節(jié)點(diǎn)的寬段,其表示為: rgt - lft + 1 所以我們可以這樣寫(xiě)存儲(chǔ)過(guò)程:

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

移動(dòng)節(jié)點(diǎn),是一個(gè)比較復(fù)雜的過(guò)程,例如下圖,macOS 應(yīng)該歸類(lèi)到 Unix 分類(lèi)下。

樹(shù)狀數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)方式的案例

要實(shí)現(xiàn)節(jié)點(diǎn)的移動(dòng),需要三步:

1、將要移動(dòng)的節(jié)點(diǎn)摘出來(lái)

2、重新編排 lft 和 rgt 參數(shù)

3、將節(jié)點(diǎn)移動(dòng)到指定位置

LOCK TABLE categories WRITE;
-- 將要移動(dòng)的節(jié)點(diǎn)摘出來(lái),并且重新邊篇 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;
-- 將節(jié)點(diǎn)放到 Unix 節(jié)點(diǎn)里
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;

總結(jié)

其實(shí) SQL 中的嵌套集合的數(shù)據(jù)模型已經(jīng)提出很久了,也有很多包已經(jīng)實(shí)現(xiàn)了這個(gè)功能,比如 laravel-nestedset 或者 django-mptt

對(duì)于生產(chǎn)使用中,肯定是沒(méi)有這么簡(jiǎn)單的表結(jié)構(gòu)設(shè)計(jì),或者甚至別的優(yōu)化,比如一種稱為閉合表的數(shù)據(jù)模型,這個(gè)應(yīng)該會(huì)在本系列文章中介紹給大家。

以上是樹(shù)狀數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)方式的案例的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對(duì)大家有幫助,更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI