您好,登錄后才能下訂單哦!
這篇文章主要介紹樹(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í)現(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è)資訊頻道!
免責(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)容。