X-Spirit
Always Beyond the Time
BlogJava
|
首頁
|
發新隨筆
|
發新文章
|
聯系
|
聚合
|
管理
隨筆:91 文章:1 評論:65 引用:0
[導入][轉]采用左右值編碼來存儲無限分級樹形結構的數據庫表設計2
采用左右值編碼的設計方案,在進行類別樹的遍歷時,由于只需進行
2次查詢,消除了遞歸,再加上查詢條件都為數字比較,效率極高,類別樹的記錄條目越多,執行效率越高。看到這里,相信不少人對這種設計方案有所心動了,下面讓我們接著看看如何在這種表結構中實現插入、刪除、同層平移節點(變更同層節點排序)的功能。
?
假定我們要在節點“肉類”下添加一個子節點“牛肉”,該樹將變成:
???????????????????????????????????? 1商品18+2
????????????????????? +--------------------------------------------+
??????????????? 2食品11+2????????????????????????????????? 12+2電器17+2
????????? +-----------------+??????????????????????????????????? +-------------------------+
??? 3肉類6+2?? 7+2蔬菜類10+2???????? 13+2電視機14+2??? 15+2電冰箱16+2
??? +-------------+
4豬肉5?
6牛肉7
? 8+2白菜9+2
?
看完上圖相應節點左右值的變化后,相信大家都知道該如何寫相應的
sql腳本吧?下面我給出相對完整的插入子節點的存儲過程:
CREATE
?
PROCEDURE
?
[
dbo
]
.
[
AddSubNodeByNode
]
(
???
@type_id
?
int
,
???
@name
?
varchar
(
50
)
)
AS
declare
?
@rgt
?
int
if
?
exists
(
select
?
1
?
from
tree
where
type_id
=
@type_id
)
???
begin
??????
SET
XACT_ABORT
ON
??????
BEGIN
?
TRANSACTION
???????
select
?
@rgt
=
rgt
from
tree
where
type_id
=
@type_id
???????
update
tree
set
rgt
=
rgt
+
2
?
where
rgt
>=
@rgt
???????
update
tree
set
lft
=
lft
+
2
?
where
lft
>=
@rgt
???????
insert
?
into
tree (name,lft,rgt)
values
(
@name
,
@rgt
,
@rgt
+
1
)???
???????
COMMIT
?
TRANSACTION
??????
SET
XACT_ABORT
OFF
???
???
end
go
?
然后,我們刪除節點“電視機”,再來看看該樹會變成什么情況:
??????????????????????????????????????????? 1商品20-2
?????????????????????? +-----------------------------------+
??????????????? 2食品13??????????????????????????????? 14電器19-2
????????? +-----------------+???????????????
?????? 3肉類8????????? 9蔬菜類12????????????? 17-2電冰箱18-2
??? +----------+
4豬肉5? 6牛肉7? 10白菜11
?
相應的存儲過程如下:
CREATE
?
PROCEDURE
?
[
dbo
]
.
[
DelNode
]
?
???
@type_id
?
int
AS
declare
?
@lft
?
int
declare
?
@rgt
?
int
if
?
exists
(
select
?
1
?
from
tree
where
type_id
=
@type_id
)
???
begin
??????
SET
XACT_ABORT
ON
??????
BEGIN
?
TRANSACTION
???????
select
?
@lft
=
lft,
@rgt
=
rgt
from
tree
where
type_id
=
@type_id
???????
delete
?
from
tree
where
lft
>=
@lft
?
and
rgt
<=
@rgt
???????
update
tree
set
lft
=
lft
-
(
@rgt
-
@lft
+
1
)
where
lft
>
@lft
???????
update
tree
set
rgt
=
rgt
-
(
@rgt
-
@lft
+
1
)
where
rgt
>
@rgt
???????
COMMIT
?
TRANSACTION
??????
SET
XACT_ABORT
OFF
???
End
?
注意:因為刪除某個節點會同時刪除該節點的所有子孫節點,而這些被刪除的節點的個數為:(被刪節點的右值-被刪節點的左值+1)/2,而任何一個節點同時具有唯一的左值和唯一的右值,故刪除作廢節點后,其他相應節點的左、右值需要調整的幅度應為:減少(被刪節點的右值-被刪節點的左值+1)。
?
? 最后,讓我們看看平移節點“電器”,將其和其所有子孫節點移動到節點“食品”之前后,該樹會變成什么情況:
?
1商品18
+-----------------------------------+
??????????????? 14-12電器17-12????????????????????? 2+4食品13+4
?????????????????????????????????????????????????????????????? +----------------------+???????????????
???????????? 15-12電冰箱16-12????? 3+4肉類8+4????? 9+4蔬菜類12+4???????
??????????????????????????????????????????????? +-------------------+
????????????????????????????????????? 4+4豬肉5+4???? 6+4牛肉7+4 10+4白菜11+4
?
大家仔細觀察一下交換后同層
2個節點和其所有子孫節點左右值的變化,可以發現一個明顯的規律,那就是,節點“電器”及其所有子孫節點的左右值均減少12,而節點“食品”及其所有子孫節點的左右值均增加4。而節點“電器”+其子孫節點的數量為2,節點“食品”+其子孫節點的數量為6,這其中有什么聯系嗎?還記得我在刪除節點的存儲過程后面的注釋嗎?
任何一個節點同時具有唯一的左值和唯一的右值。讓我們把節點數量*2,正好和節點左右值需要調整的幅度相等。由此規律,我們可以編寫出類似下面的存儲過程來實現節點同層前移的功能:
CREATE
?
PROCEDURE
?
[
dbo
]
.
[
MoveNodeUp
]
?
???
@type_id
?
int
AS
declare
?
@lft
?
int
declare
?
@rgt
?
int
declare
?
@layer
?
int
if
?
exists
(
select
?
1
?
from
tree
where
type_id
=
@type_id
)
???
begin
??????
SET
XACT_ABORT
ON
??????
BEGIN
?
TRANSACTION
???????
select
?
@lft
=
lft,
@rgt
=
rgt,
@layer
=
layer
from
TreeView
where
type_id
=
@type_id
???????
if
?
exists
(
select
?
*
?
from
TreeView
where
rgt
=
@lft
-
1
?
and
layer
=
@layer
)
??????????
begin
??????????????
declare
?
@brother_lft
?
int
??????????????
declare
?
@brother_rgt
?
int
??????????????
select
?
@brother_lft
=
lft,
@brother_rgt
=
rgt
from
TreeView
where
rgt
=
@lft
-
1
?
and
layer
=
@layer
??????????????
update
tree
set
lft
=
lft
-
(
@brother_rgt
-
@brother_lft
+
1
)
where
lft
>=
@lft
?
and
rgt
<=
@rgt
??????????????
update
tree
set
lft
=
lft
+
(
@rgt
-
@lft
+
1
)
where
lft
>=
@brother_lft
?
and
rgt
<=
@brother_rgt
??????????????
update
tree
set
rgt
=
rgt
-
(
@brother_rgt
-
@brother_lft
+
1
)
where
rgt
>
@brother_rgt
?
and
rgt
<=
@rgt
??????????????
update
tree
set
rgt
=
rgt
+
(
@rgt
-
@lft
+
1
)
where
lft
>=
@brother_lft
+
(
@rgt
-
@lft
+
1
)
and
rgt
<=
@brother_rgt
??????????
end
???????
COMMIT
?
TRANSACTION
??????
SET
XACT_ABORT
OFF
???
???
end
?
注意:節點的同層平移可以采用臨時表來做中介,降低代碼的復雜度。不用臨時表來處理也行,但是
update語句順序一定要考慮周詳。否則,一旦出現bug,對整個類別表的破壞是驚人的,強烈推薦在做上述工作前對類別表進行完整備份。
?
同層下移的存儲過程和同層上移類似,有興趣的朋友可以自己動手編寫體味一下其中的細節,我就不在這里列出來了。
?
最后,我對上面這種左右值編碼實現無限分級類別樹的方案做一個總結:
優點:在消除遞歸的前提下實現了無限分級,而且查詢條件是基于整形數字比較的,效率很高。可以進行先序列表,添加,修改,刪除,同層平移等常規操作,基本滿足需求。
缺點:由于這種左右值編碼的方式和常見的阿拉伯數字直觀排序不同,再加上節點在樹中的層次,順序不是直觀顯示出來,而必須通過簡單的公式計算后得到,需要花費一定的時間對其數學模型進行深入理解。而且,采用該方案編寫相關存儲過程,新增,刪除,同層平移節點需要對整個樹進行查詢修改,由此導致的代碼復雜度,耦合度較高,修改維護的風險較高。
?
文章來源:
http://x-spirit.spaces.live.com/Blog/cns!CC0B04AE126337C0!368.entry
發表于 2007-12-18 20:02
X-Spirit
閱讀(261)
評論(0)
編輯
收藏
新用戶注冊
刷新評論列表
只有注冊用戶
登錄
后才能發表評論。
網站導航:
博客園
IT新聞
Chat2DB
C++博客
博問
管理
<
2007年12月
>
日
一
二
三
四
五
六
25
26
27
28
29
30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
常用鏈接
我的隨筆
我的文章
我的評論
我的參與
最新評論
留言簿
(6)
給我留言
查看公開留言
查看私人留言
隨筆分類
(28)
Big Data
(rss)
Cloud
(rss)
Java EE
(rss)
Java FX
(rss)
Java SE(9)
(rss)
Java 輕量級企業開發(5)
(rss)
Linux(3)
(rss)
MySQL
(rss)
NetBeans(1)
(rss)
Node.js
(rss)
NoSQL
(rss)
Oracle(3)
(rss)
前端技術
(rss)
開源協議(1)
(rss)
思維模式
(rss)
悟(1)
(rss)
技術之外(5)
(rss)
敏捷開發
(rss)
時間管理
(rss)
隨筆檔案
(90)
2014年9月 (1)
2014年3月 (1)
2014年2月 (1)
2014年1月 (1)
2013年2月 (1)
2012年11月 (1)
2012年10月 (1)
2012年3月 (1)
2012年2月 (1)
2011年2月 (1)
2010年4月 (6)
2010年3月 (4)
2010年1月 (2)
2009年11月 (1)
2009年8月 (1)
2009年7月 (1)
2009年6月 (2)
2009年5月 (1)
2009年4月 (13)
2009年3月 (1)
2009年2月 (1)
2009年1月 (2)
2008年12月 (3)
2008年11月 (1)
2008年10月 (1)
2008年9月 (3)
2008年5月 (1)
2008年4月 (9)
2008年3月 (3)
2008年1月 (1)
2007年12月 (4)
2007年10月 (2)
2007年9月 (6)
2007年8月 (9)
2007年7月 (1)
2007年4月 (1)
文章分類
(1)
My Voice(1)
(rss)
文章檔案
(1)
2009年12月 (1)
收藏夾
(4)
別人的學習筆記(4)
(rss)
牛人牛博
DaoRu的Blog
(rss)
愛折騰的道儒
Doug Lea's Home Page
Doug Lea's Home Page
jolestar
老王的博客
Tim Yang
(rss)
后端技術
Yang_net
(rss)
靠譜IT帥哥
搖擺巴赫@blog.sina
源碼控
搖擺巴赫@javaeye
源碼控
文初的一畝三分地
淘寶放翁
淘寶核心團隊
淘寶核心團隊
福林雨
(rss)
福林的博客
那誰的BLOG
那誰的BLOG
酷站
ImportNew
學習新知、發現新朋友
InfoQ中文站
InfoQ中文站
InfoQ英文站
InfoQ英文站
Java Code Geeks
A website for Java Geeks
并發編程網
并發編程網
開源中國
OSCHINA
百度技術沙龍
百度技術沙龍
酷殼
(rss)
酷殼
最新隨筆
1.?【Math's History】什么是羅素悖論
2.?【Effective】IntelliJ IDEA MAC IDE config files
3.?5 Ways To Burn Out Programming
4.?【Efficiency】快速配置ubuntu桌面環境之Java環境配置[全軟件源安裝]
5.?【Efficiency】MAC下使用設定可以從mission control中啟動的eclipse.app。
6.?【Effective】如何遷移git倉庫
7.?【轉】閱讀我們的學科——計算機專業學習淺談
8.?【Tech Details】【轉】有關Java SPI機制
9.?【Efficiency】 監控 Linux 性能的 18 個命令行工具
10.?【Effective】Logging最佳實踐
搜索
最新評論
1.?re: Java 多線程同步問題的探究(三、Lock來了,大家都讓開【1. 認識重入鎖】)
上班
--地點
2.?re: 【轉】閱讀我們的學科——計算機專業學習淺談
好文!
--何楊
3.?re: [導入][轉]重復提交、重復刷新、防止后退的問題以及處理方式
是多少
--乒乓、
4.?......
....
--..
5.?re: Java多線程同步問題的探究(一、線程的先來后到)
多線程這塊一直是軟肋,學習一下,呵呵
--FlyingFish
閱讀排行榜
1.?Java 多線程同步問題的探究(三、Lock來了,大家都讓開【1. 認識重入鎖】)(9054)
2.?Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發安全性?)【更新重要補疑】(8411)
3.?Java 多線程同步問題的探究(二、給我一把鎖,我能創造一個規矩)(7440)
4.?Java 多線程同步問題的探究(四、協作,互斥下的協作——Java多線程協作(wait、notify、notifyAll))(7252)
5.?Java多線程同步問題的探究(一、線程的先來后到)(7104)
評論排行榜
1.?Java 多線程同步問題的探究(五、你有我有全都有—— ThreadLocal如何解決并發安全性?)【更新重要補疑】(15)
2.?Java 多線程同步問題的探究(三、Lock來了,大家都讓開【1. 認識重入鎖】)(10)
3.?Java 多線程同步問題的探究(二、給我一把鎖,我能創造一個規矩)(9)
4.?Java 多線程同步問題的探究(四、協作,互斥下的協作——Java多線程協作(wait、notify、notifyAll))(9)
5.?Java多線程同步問題的探究(一、線程的先來后到)(8)
Powered by:
博客園
模板提供:
滬江博客
Copyright ©2025 X-Spirit
主站蜘蛛池模板:
97青青草原国产免费观看
|
黄色免费网站在线看
|
a视频在线观看免费
|
狠狠色婷婷狠狠狠亚洲综合
|
美女隐私免费视频看
|
中文字幕第13亚洲另类
|
a视频免费在线观看
|
亚洲AV无码一区东京热久久
|
97av免费视频
|
亚洲国产日韩在线成人蜜芽
|
福利免费观看午夜体检区
|
亚洲乱亚洲乱妇24p
|
四虎免费永久在线播放
|
日本黄页网址在线看免费不卡
|
狠狠亚洲狠狠欧洲2019
|
十八禁无码免费网站
|
亚洲一级毛片在线观
|
日韩毛片免费在线观看
|
久久国产乱子伦精品免费午夜
|
亚洲AV永久无码精品一百度影院
|
67194成手机免费观看
|
亚洲日韩久久综合中文字幕
|
亚洲AⅤ无码一区二区三区在线
|
igao激情在线视频免费
|
亚洲精品综合一二三区在线
|
99久久这里只精品国产免费
|
羞羞漫画小舞被黄漫免费
|
国产成人A人亚洲精品无码
|
69av免费观看
|
免费一级毛片在线播放视频免费观看永久
|
久久久久亚洲精品无码网址
|
亚洲第一成年男人的天堂
|
在线日本高清免费不卡
|
亚洲av无码成人精品国产
|
久久精品国产亚洲一区二区
|
最好看的中文字幕2019免费
|
亚洲精品动漫免费二区
|
亚洲AV永久无码精品
|
在线观看免费为成年视频
|
久久久久女教师免费一区
|
亚洲综合亚洲国产尤物
|