[SQL Server]树形结构的创建
對(duì)于SQL Server來說,構(gòu)建顯示一個(gè)樹形結(jié)構(gòu)不是一件容易的事情,邏輯構(gòu)造能力不是它的強(qiáng)項(xiàng)。不過也不是說它沒有能力干這個(gè)事情,只要換一種思維方式就可以理解它的工作原理。
例如,現(xiàn)在有一張表的內(nèi)容如下:
CategoryNO CategoryName?????????????????????????????????????? Parent
---------- -------------------------------------------------- ------
0????????? ROOT?????????????????????????????????????????????? NULL
1????????? .NET?????????????????????????????????????????????? 0
2????????? DataBase?????????????????????????????????????????? 0
3????????? Java?????????????????????????????????????????????? 0
4????????? Others???????????????????????????????????????????? 0
5????????? WindowsOS????????????????????????????????????????? 0
6????????? F#???????????????????????????????????????????????? 1
7????????? C#???????????????????????????????????????????????? 1
8????????? WPF??????????????????????????????????????????????? 1
9????????? VB.NET???????????????????????????????????????????? 1
10???????? SQL Server???????????????????????????????????????? 2
11???????? J2SE?????????????????????????????????????????????? 3
12???????? 批處理????????????????????????????????????????????? 5
13???????? 注冊(cè)表????????????????????????????????????????????? 5
14???????? SliverLight??????????????????????????????????????? 8
15???????? 基本命令?????????????????????????????????????????? ?12
16???????? 擴(kuò)展命令?????????????????????????????????????????? ?12
17???????? HKLM?????????????????????????????????????????????? 13
18???????? HKCU?????????????????????????????????????????????? 13
19???????? DIR??????????????????????????????????????????????? 15
20???????? COPY?????????????????????????????????????????????? 15
21???????? DEL??????????????????????????????????????????????? 15
22???????? IE???????????????????????????????????????????????? 5
23???????? LINQ?????????????????????????????????????????????? 1
24???????? C++??????????????????????????????????????????????? 0
它看上去是多么混亂無(wú)序,我們希望它能按如下方式顯示,也就是所謂的樹形結(jié)構(gòu):
CategoryNO? CategoryName
----------- --------------------
1?????????? .NET???????????????
6?????????????? F#?????????????
7?????????????? C#??????????????
8?????????????? WPF?????????????
14????????????????? SliverLight?
9?????????????? VB.NET??????????
23????????????? LINQ????????????
2?????????? DataBase????????????
10????????????? SQL Server?????
3?????????? Java????????????????
11????????????? J2SE????????????
4?????????? Others??????????????
5?????????? WindowsOS???????????
12????????????? 批處理??????????
15????????????????? 基本命令????
19????????????????????? DIR?????
20????????????????????? COPY????
21????????????????????? DEL?????
16????????????????? 擴(kuò)展命令????
13????????????? 注冊(cè)表?????????
17????????????????? HKLM????????
18????????????????? HKCU???????
22????????????? IE????????????
24????????? C++????
至少這樣看上去好多了?,F(xiàn)在來看看如何實(shí)現(xiàn)這個(gè)功能。
首先我們需要一個(gè)變量來記錄當(dāng)前進(jìn)入到樹形結(jié)構(gòu)的哪個(gè)級(jí)別,并把它設(shè)置為0,表示第一個(gè)級(jí)別;以及另一個(gè)變量來記錄當(dāng)前在對(duì)哪條記錄操作。
DECLARE?@CategoryNO?int,?@Level?intSET?@Level?=?0
?
然后要建立兩張臨時(shí)表,第一張表用來存儲(chǔ)待處理記錄,第二張表存儲(chǔ)最終的結(jié)果。關(guān)于它們是如何使用的請(qǐng)繼續(xù)往下看。
(
?CategoryNO?int?NOT?NULL,
?CategoryName?nvarchar(30)?NOT?NULL,
?Parent?int?NULL,
?[Level]?int?NOT?NULL
)
CREATE?TABLE?#TreeViewResult
(
?CategoryNO?int?NOT?NULL,
?CategoryName?nvarchar(30)?NOT?NULL
)
接下來向#TreeViewTemp表中插入第一級(jí)別的記錄。在這里,ROOT記錄表示的是根級(jí)別,是所有第一級(jí)別的父級(jí),最終結(jié)果將不包含該記錄。注意#TreeViewTemp表中記錄了這些記錄的級(jí)別。
SELECT?CategoryNO,?CategoryName,?Parent,?@Level
FROM?Category
WHERE?Parent?=?0
?
再下來,進(jìn)入一個(gè)循環(huán)結(jié)構(gòu)。循環(huán)結(jié)束的條件是#TreeViewTemp表中不再有記錄。接下來的內(nèi)容都是在循環(huán)結(jié)構(gòu)中的,BEGIN和END關(guān)鍵字就不寫出來了。
WHILE?EXISTS?(SELECT?CategoryNO?FROM?#TreeViewTemp)?
循環(huán)的第一條語(yǔ)句,取出#TreeViewTemp中當(dāng)前級(jí)別的第一條記錄,并記錄下它的CategoryNO(還記得一開始的@CategoryNO和@Level變量嗎?)
SELECT?TOP(1)?@CategoryNO?=?CategoryNOFROM?#TreeViewTemp
WHERE?[Level]?=?@Level
ORDER?BY?CategoryNO
?
如果取不到記錄,也就是說臨時(shí)表中當(dāng)前級(jí)別的記錄不存在,那么令@Level變量的值減一,也就是退回上一級(jí)別,并繼續(xù)下一個(gè)循環(huán)。
IF?@@ROWCOUNT?=?0BEGIN
?SET?@Level?=?@Level?-?1
?CONTINUE
END
?
如果當(dāng)前級(jí)別還有記錄,就把這條記錄插入到最終結(jié)果的表中。插入的時(shí)候根據(jù)當(dāng)前級(jí)別在名稱前面加上空格。
INSERT?#TreeViewResultSELECT?CategoryNO,?SPACE(4?*?@Level)?+?CategoryName
FROM?#TreeViewTemp
WHERE?CategoryNO?=?@CategoryNO
?
接著找出剛剛那條記錄的所有子類別,插入到#TreeViewTemp表中。這里把@Level的值加1再插入到表中,表明這些記錄是下一級(jí)別的。
INSERT?#TreeViewTempSELECT?CategoryNO,?CategoryName,?Parent,?@Level?+?1
FROM?Category
WHERE?Parent?=?@CategoryNO
?
如果這條記錄有子類別,那么就使@Level的值加1,進(jìn)入下一級(jí)別。
IF?@@ROWCOUNT?<>?0?SET?@Level?=?@Level?+?1
?
循環(huán)結(jié)構(gòu)中最后一條語(yǔ)句,把#TreeViewTemp中剛剛處理的那條記錄刪除。
DELETE?#TreeViewTempWHERE?CategoryNO?=?@CategoryNO
?
最后一件事,當(dāng)然是把最終的結(jié)果顯示出來了。
SELECT?CategoryNO,?CategoryName?FROM?#TreeViewResult?
最最后的,把臨時(shí)表刪除。
DROP?TABLE?#TreeViewTempDROP?TABLE?#TreeViewResult
?
好了,構(gòu)建樹形結(jié)構(gòu)的基本框架就是這樣,可以在這個(gè)基礎(chǔ)上作些修改以適應(yīng)不同的需求。
我不知道以上說明是否能讓大家明白這個(gè)邏輯,甚至我自己也說不清楚,它實(shí)在是比較復(fù)雜……
這個(gè)方法有一個(gè)缺點(diǎn),就是使用了臨時(shí)表。由于臨時(shí)表的數(shù)據(jù)是存儲(chǔ)在硬盤中的,所以整個(gè)過程的速度會(huì)有影響。
在最后把整個(gè)過程的代碼整合在一起:
DECLARE?@CategoryNO?int,?@Level?int
SET?@Level?=?0
CREATE?TABLE?#TreeViewTemp
(
?CategoryNO?int?NOT?NULL,
?CategoryName?nvarchar(30)?NOT?NULL,
?Parent?int?NULL,
?[Level]?int?NOT?NULL
)
CREATE?TABLE?#TreeViewResult
(
?CategoryNO?int?NOT?NULL,
?CategoryName?nvarchar(30)?NOT?NULL
)
INSERT?#TreeViewTemp
SELECT?CategoryNO,?CategoryName,?Parent,?@Level
FROM?Category
WHERE?Parent?=?0
WHILE?EXISTS?(SELECT?CategoryNO?FROM?#TreeViewTemp)
BEGIN
?SELECT?TOP(1)?@CategoryNO?=?CategoryNO
?FROM?#TreeViewTemp
?WHERE?[Level]?=?@Level
?ORDER?BY?CategoryNO
?IF?@@ROWCOUNT?=?0
?BEGIN
??SET?@Level?=?@Level?-?1
??CONTINUE
?END
?INSERT?#TreeViewResult
?SELECT?CategoryNO,?SPACE(4?*?@Level)?+?CategoryName
?FROM?#TreeViewTemp
?WHERE?CategoryNO?=?@CategoryNO
?INSERT?#TreeViewTemp
?SELECT?CategoryNO,?CategoryName,?Parent,?@Level?+?1
?FROM?Category
?WHERE?Parent?=?@CategoryNO
?IF?@@ROWCOUNT?<>?0
??SET?@Level?=?@Level?+?1
?
?DELETE?#TreeViewTemp
?WHERE?CategoryNO?=?@CategoryNO
END
SELECT?CategoryNO,?CategoryName?FROM?#TreeViewResult
DROP?TABLE?#TreeViewTemp
DROP?TABLE?#TreeViewResult
轉(zhuǎn)載于:https://www.cnblogs.com/zplutor/archive/2009/07/31/1536146.html
總結(jié)
以上是生活随笔為你收集整理的[SQL Server]树形结构的创建的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: COM编程入门---转发
- 下一篇: C#连接4种类型数据库(Access、S