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