由於工作原因,涉及到一個樹狀存放記錄的表,要求程序中把樹狀表全部展開,並輸出相應的數據內容。由於涉及到此種操作的地方很多,比如網絡上的\\\"論壇"就是典型的采用樹狀存放記錄的表,特此整理出來與大家分享。
在很多資料都有介紹展開樹狀記錄的程序,但是很多是采用遞歸的方法。我們知道,遞歸的方法邏輯比較簡單,實際操作起來比較容易。但是遞歸有一個最大的缺點就是占用資源太多,速度太慢。如果在互聯網的"論壇"上采用此種方法,在表記錄很多的情況下將是一個非常嚴重的問題。下面的程序在筆者的工作中解決了一個大問題並將應用於本人小站(yuking.126.com)的論壇。
我這裡采用速度非常快的堆棧來實現這種操作,但是操作起來相對而言難度加大。我們就以論壇記錄表為例講解這一過程,首先了解一下表結構:
一、表結構(article)
self int '本記錄ID號
father int '父記錄ID號
title char '貼子標題
author char '貼子作者
datetime date '發貼日期時間
hits int '點擊數
reply int '回復數
..... '根據具體的情況我們還可以有更多的字段
1)關鍵說明:self是記錄本記錄的ID號,這應該是一個自動增長的字段,不充許重復。father是記錄本結點的父結點ID號的字段,若該記錄內容為"回貼"此字段值應該為"主貼"的ID號。若該記錄為"主貼"則它的父結點應該為"0"
2)如下兩條記錄是父子記錄:
self father title author .....
1 0 '誰能幫幫我' '三腳貓'
2 1 '我能幫你什麼忙嗎?' '網上飛'
二、操作方法
首先,我們讀出所有父結點為"0"的記錄也就是"主貼",統統放入堆棧中。然後輸出位於棧頂的一條記錄("主貼")數據,並清空棧頂,棧頂下移一格。接著查找所有父結點為該棧項結點("主貼")的記錄("回貼"),也統統放於棧頂。注意到沒有,就這兩步我們就完成了把一條父記錄輸出並展開其子結點的工作。余下的工作只是依次類推而已了,直到棧為空為止。
當然實際操作時可能還會有一些要求,比如要求得到記錄的層數,回復數等等問題,我們只需稍加改進就能實現。
三、這裡是整理後的原代碼
<%
set RS=server.CreateObject("ADODB.Recordset")
sql_text="select * from article where father=0 order by datetime desc"
RS.Open sql_text,Bbs_ConnectionString '查找所有父結點為'0'的結點,即"主貼"。
Dim Stack(100,8) '定義堆棧,我這裡是100('8'是指每個棧元素分別存放8個字段值)。'可根據實際情況定義堆棧大小,可以按這個公式計算"最多層數*最多展開數"。
while not Rs.eof
Stack(0,0)=RS("self")
Stack(0,1)=RS("father")
Stack(0,2)=RS("title")
Stack(0,3)=RS("author")
Stack(0,4)=RS("datetime")
Stack(0,5)=RS("hits")
Stack(0,6)=RS("reply")
Stack(0,7)=0
Top=1
do until Top=0
Sql_text="select * from article where father="&StackTop&"
RS1.Open Sql_text,MyConn '查找所有父結點為棧頂結點的記錄
'輸出棧項元素,我這裡是直接輸出,實際做的時候可以產生表格等等效果
for i=0 to 7
Response.write stack(top-1,i)
next
ParentLevel=stack(top-1,7) '清空堆棧之前獲得父記錄的層數
for i=0 to 7 '清空堆棧項部
Stack(top-1,i)=""
next
Top=top-1 '棧頂向下移動一格
'將查找到的棧項結點"派生出"的全部子記錄存入堆棧
While not RS1.eof
Stack(Top,0)=RS1("self")
Stack(Top,1)=RS1("father")
Stack(Top,2)=RS1("title")
Stack(Top,3)=RS1("author")
Stack(Top,4)=RS1("datetime")
Stack(Top,5)=RS1("hits")
Stack(Top,6)=RS1("reply")
Stack(Top,7)=ParentLevel+1
Rs1.movenext
Top=Top+1 '棧項向上移動
Wend
Rs1.close
loop
Rs.MoveNext '移動到下一條記錄
Wend
Rs.close
set Rs=nothing
set Rs1=nothing
%>