bbs的树形结构显示可以有很多种方法,其中比较容易想到的是递归和排序串方法,但这两种方法并不是很好,那么怎样才算是比较合理的算法呢?
递归方法不用讲,大家都知道怎么用,先讲讲排序串方法,最简单的排序串方法可以这样用,只用一个id就可以完成树型,向这样
1 001
2 002
3 001001
4 001001001
5 001002001
用这个字符串排序后就变成这样:
001
001001
001001001
001002001
002
这种方法容易实现,但缺点也是很明显,一个是回帖数受限制,另一个随着回帖增加会越来越长,影响数据库效率。
下面一种方法是李龙的,属于变通的排序串方法
ddl
————–
create table dbo.message
(
id numeric(18,0) identity(1000,1),
dateandtime datetime default getdate() not null,
authorid numeric(18,0) not null,
subject nvarchar(250) not null,
body ntext null,
linkurl nvarchar(100) null,
textforlink nvarchar(50) null,
imageurl nvarchar(100) null,
class int default 0 not null,
clientinfo nvarchar(250) null,
remoteaddr nvarchar(50) null,
constraint pk_bbsmessage
primary key nonclustered (id,authorid)
)
go
create table dbo.msgreftab
(
msgid numeric(18,0) not null,
parentid numeric(18,0) not null,
ancestorid numeric(18,0) not null,
childnum numeric(18,0) default 0 not null,
linkstr nvarchar(250) not null,
constraint pk_bbsreftab
primary key nonclustered (msgid)
)
go
—————–
存储过程:
—————–
— 抽出
create procedure sp_summary
@havebody bit,
@from numeric,
@to numeric
as
if (@havebody = 1)
select t.id,t.dateandtime,m.nickname as
author,m.email,t.subject,t.body,t.linkurl,t.textforlink,t.imageurl,s.childnu
m,s.parentid
from message t
,msgreftab as s
,(select msgid from msgreftab where parentid = 0) as f
,members as m
where t.id=s.msgid
and f.msgid = s.ancestorid
and f.msgid between @from and @to
and m.memberid = t.authorid
order by s.ancestorid,s.linkstr
else
select t.id,t.dateandtime,m.nickname as
author,m.email,t.subject,t.linkurl,t.textforlink,t.imageurl,s.childnum,s.par
entid
from message t
,msgreftab as s
,(select msgid from msgreftab where parentid = 0) as f
,members as m
where t.id=s.msgid
and f.msgid = s.ancestorid
and f.msgid between @from and @to
and m.memberid = t.authorid
order by s.ancestorid,s.linkstr
go
— 加贴
create procedure sp_add_message
@authorid numeric,
@subject nvarchar(250),
@body ntext,
@linkurl nvarchar(100),
@textforlink nvarchar(50),
@imageurl nvarchar(100),
@parentid numeric,
@id numeric output,
@childnum numeric output,
@linkstr nvarchar(250) output,
@ancestorid numeric output
as
insert into message(
authorid,
subject,
body,
linkurl,
textforlink,
imageurl)
values(
@authorid,
@subject,
@body,
@linkurl,
@textforlink,
@imageurl)
select @id = @@identity
update msgreftab
set
childnum = childnum+1
where
msgid = @parentid
select @childnum = childnum,
@linkstr = linkstr,
@ancestorid = ancestorid
from msgreftab
where
msgid = @parentid
go
—
是基于这样的想法:
贴子和跟贴都放在message表里,另有msgreftab对每一条信息都有描述。
父贴parentid,0为不是子贴
祖宗贴ancestorid
直接跟贴数childnum
联接串linkstr,学问都在这里,所有的跟贴都用一个数字字符串表示
如是
1011—> 为空
1012—>001 1011的跟贴,父贴linkstr+父贴的子贴数+1
1013—>001001 1012的跟贴,父贴linkstr+父贴的子贴数+1
1018—>001001001 1013的跟贴,父贴linkstr+父贴的子贴数+1
1014—>001002 1012的跟贴,父贴linkstr+父贴的子贴数+1
1017—>001002001 1014的跟贴,父贴linkstr+父贴的子贴数+1
部分演示数据:
msgid parentid ancestorid childnum linkstr
1010 0 1010 0
1011 0 1011 1
1012 1011 1011 3 001
1013 1012 1011 1 001001
1014 1012 1011 1 001002
1015 0 1015 0
1017 1014 1011 0 001002001
1018 1013 1011 0 001001001
就是算法复杂一点,但只使用select就得到了正确的结构列表。
看了这么多bbs的算法,还是觉得自己的方法好,现实中由存储过程直接生成xml文档,交
给client。
