預(yù)排序樹實現(xiàn)無限極分類

一.概念

  • 左右值無限級分類闰围,也稱為預(yù)排序樹無限級分類
  • 是一種有序的樹狀結(jié)構(gòu)
  • 于這些樹狀結(jié)構(gòu)中的每一個節(jié)點都有一個 左值右值

二.規(guī)則

  • 每一個 后代節(jié)點左值 > 父節(jié)點左值
  • 每一個 后代節(jié)點右值 < 父節(jié)點右值
  • 每一個節(jié)點的 右值 < 左值
    Paste_Image.png

三.新增節(jié)點

  • 新增頂級分類:
    • 獲取該樹中 最大右值;
    • 左值 = 最大右值 + 1;
    • 右值 = 最大右值 + 2;
  • 新增子節(jié)點
    • 首先獲取 父節(jié)點右值
    UPDATE `catagory` SET `lft` = `lft`+2 WHERE `lft`>`父節(jié)點右值`
    UPDATE `catagory` SET `rgt` = `rgt` + 2 WHERE `rgt`>= `父節(jié)點右值`
    
    • 新增節(jié)點左值 = 父節(jié)點右值
    • 新增節(jié)點右值 = 新增節(jié)點左值 + 1

四. 刪除節(jié)點

  • 獲取刪除節(jié)點的左右值 $lft, $rgt
  • 刪除該節(jié)點以及所有后代節(jié)點
DELETE FROM `catagory` WHERE `lft`>=$lft AND `rgt`<=$Rgt"
  • 更新左右值
$Value=$rgt-$lft+1;
UPDATE `catagory` SET `lft`=`lft`- $Value WHERE `lft`>$lft
UPDATE `catagory` SET `rgt`=`rgt`- $Value WHERE `rgt`>$rgt"

五.數(shù)據(jù)準備

CREATE TABLE `nested_category` (
  `category_id` int(10) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
  `name` varchar(18) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '名稱',
  `lft` int(4) NOT NULL,
  `rgt` int(4) NOT NULL,
  KEY `category_id` (`category_id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

INSERT INTO `nested_category` VALUES 
(1,'商品',1,26),
(2,'化妝品',2,7),
(3,'食品',8,9),
(4,'酒',10,15),
(5,'服裝',16,17),
(6,'家電',18,23),
(7,'鞋帽',24,25),
(8,'面霜',3,4),
(9,'面膜',5,6),
(10,'白酒',11,12),
(11,'紅酒',13,14),
(12,'冰箱',19,20),
(13,'空調(diào)',21,22);

數(shù)據(jù)查看
mysql> select * from nested_category;
+-------------+-----------+-----+-----+
| category_id | name      | lft | rgt |
+-------------+-----------+-----+-----+
|           1 | 商品    |   1 |  26 |
|           2 | 化妝品 |   2 |   7 |
|           3 | 食品    |   8 |   9 |
|           4 | 酒       |  10 |  15 |
|           5 | 服裝    |  16 |  17 |
|           6 | 家電    |  18 |  23 |
|           7 | 鞋帽    |  24 |  25 |
|           8 | 面霜    |   3 |   4 |
|           9 | 面膜    |   5 |   6 |
|          10 | 白酒    |  11 |  12 |
|          11 | 紅酒    |  13 |  14 |
|          12 | 冰箱    |  19 |  20 |
|          13 | 空調(diào)    |  21 |  22 |
+-------------+-----------+-----+-----+

六. 獲取所有后代節(jié)點

select * from nested_category where lft > 18 and rgt < 23;
+-------------+--------+-----+-----+
| category_id | name   | lft | rgt |
+-------------+--------+-----+-----+
|          12 | 冰箱 |  19 |  20 |
|          13 | 空調(diào) |  21 |  22 |
+-------------+--------+-----+-----+
2 rows in set (0.00 sec)

七.計算后代數(shù)量

  • 后代的數(shù)量 = (右值 - 左值 - 1) / 2。減少1的原因是排除該節(jié)點本身

八. 判斷葉子節(jié)點

  • 右值 - 左值 = 1
  • 獲取葉子節(jié)點
mysql> select * from nested_category  where rgt - lft = 1;
+-------------+--------+-----+-----+
| category_id | name   | lft | rgt |
+-------------+--------+-----+-----+
|           3 | 食品   |   8 |   9 |
|           5 | 服裝   |  16 |  17 |
|           7 | 鞋帽   |  24 |  25 |
|           8 | 面霜   |   3 |   4 |
|           9 | 面膜   |   5 |   6 |
|          10 | 白酒   |  11 |  12 |
|          11 | 紅酒   |  13 |  14 |
|          12 | 冰箱   |  19 |  20 |
|          13 | 空調(diào)   |  21 |  22 |
+-------------+--------+-----+-----+

九. 檢索單一路徑

select 
    parent.name,
    parent.category_id, 
    parent.lft,
    parent.rgt
from 
    nested_category as node, nested_category as parent 
where 
    node.lft between parent.lft and parent.rgt and node.name = '空調(diào)' 
    order by parent.lft;

+--------+-------------+-----+-----+
| name   | category_id | lft | rgt |
+--------+-------------+-----+-----+
| 商品 |           1 |   1 |  26 |
| 家電 |           6 |  18 |  23 |
| 空調(diào) |          13 |  21 |  22 |
+--------+-------------+-----+-----+
3 rows in set (0.00 sec)

十. 檢索分類深度

select 
    node.name as name,  (count(parent.name) - 1) as deep
from 
    nested_category as node,
    nested_category as parent
where node.lft between parent.lft and parent.rgt
group by node.name
order by node.lft
+-----------+------+
| name      | deep |
+-----------+------+
| 商品    |    0 |
| 化妝品 |    1 |
| 面霜    |    2 |
| 面膜    |    2 |
| 食品    |    1 |
| 酒       |    1 |
| 白酒    |    2 |
| 紅酒    |    2 |
| 服裝    |    1 |
| 家電    |    1 |
| 冰箱    |    2 |
| 空調(diào)    |    2 |
| 鞋帽    |    1 |
+-----------+------+
13 rows in set (0.03 sec)

十一. 檢索某個節(jié)點的子節(jié)點(不包含后代節(jié)點)

select * from (
    select 
        node.name as name,  
        (count(parent.name) - 1) as deep 
    from 
        nested_category as node,
        nested_category as parent 
    where node.lft between parent.lft and parent.rgt 
    group by node.name 
    order by node.lft
) as a where a.deep <= 1; 
+-----------+------+
| name      | deep |
+-----------+------+
| 商品    |    0 |
| 化妝品 |    1 |
| 食品    |    1 |
| 酒       |    1 |
| 服裝    |    1 |
| 家電    |    1 |
| 鞋帽    |    1 |
+-----------+------+
7 rows in set (0.00 sec)

十二.總結(jié)

  • 我們看到上邊的獲取深度檢索某個節(jié)點的子節(jié)點實現(xiàn)上用到了子查詢,sql語句很復(fù)雜.
  • 所以我的解決辦法是在數(shù)據(jù)結(jié)構(gòu)上增加 深度父id 兩個字段
  • 因為分類是前臺頁面操作人員操作的, 也就是說操作的時候就知道深度, 每次新增時候?qū)?深度父id 帶上就可以方便的解決復(fù)雜sql語句的問題;

參考文章: http://blog.csdn.net/i_bruce/article/details/41558063

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末技掏,一起剝皮案震驚了整個濱河市蔚万,隨后出現(xiàn)的幾起案子岭妖,更是在濱河造成了極大的恐慌,老刑警劉巖反璃,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件昵慌,死亡現(xiàn)場離奇詭異,居然都是意外死亡淮蜈,警方通過查閱死者的電腦和手機斋攀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來梧田,“玉大人淳蔼,你說我怎么就攤上這事侧蘸。” “怎么了鹉梨?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵讳癌,是天一觀的道長。 經(jīng)常有香客問我存皂,道長晌坤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任旦袋,我火速辦了婚禮骤菠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘疤孕。我一直安慰自己商乎,他們只是感情好,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布祭阀。 她就那樣靜靜地躺著鹉戚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪专控。 梳的紋絲不亂的頭發(fā)上崩瓤,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天,我揣著相機與錄音踩官,去河邊找鬼却桶。 笑死,一個胖子當著我的面吹牛蔗牡,可吹牛的內(nèi)容都是我干的颖系。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼辩越,長吁一口氣:“原來是場噩夢啊……” “哼嘁扼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起黔攒,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤趁啸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后督惰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體不傅,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年赏胚,在試婚紗的時候發(fā)現(xiàn)自己被綠了访娶。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡觉阅,死狀恐怖崖疤,靈堂內(nèi)的尸體忽然破棺而出秘车,到底是詐尸還是另有隱情,我是刑警寧澤劫哼,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站权烧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏豪嚎。R本人自食惡果不足惜谈火,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望糯耍。 院中可真熱鬧扔字,春花似錦温技、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜓堕。三九已至,卻和暖如春套才,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背背伴。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工傻寂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留息尺,地道東北人疾掰。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像勒葱,于是被迫代替她去往敵國和親浪汪。 傳聞我的和親對象是個殘疾皇子凛虽,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 引言 大多數(shù)用戶都曾在數(shù)據(jù)庫中處理過分層數(shù)據(jù)(hierarchical data),認為分層數(shù)據(jù)的管理不是關(guān)系數(shù)據(jù)...
    像詩人一樣依賴著月亮閱讀 2,896評論 2 3
  • 樹的概述 樹是一種非常常用的數(shù)據(jù)結(jié)構(gòu)凯旋,樹與前面介紹的線性表,棧至非,隊列等線性結(jié)構(gòu)不同钠署,樹是一種非線性結(jié)構(gòu) 1.樹的定...
    Jack921閱讀 4,452評論 1 31
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,110評論 25 707
  • 2017年5月25號徒步旅行已經(jīng)走了48天堅持繼續(xù)行走的心在路上 最近好久沒寫文字了谐鼎,不知道還是累了,還是懶了趣惠,我...
    魏東雷閱讀 293評論 1 2