树型结构是递归算法的经典实例(只怪非CS的我没有扎实的数据结构功底,鼓捣了两个半天 :P)。有个新闻分类表CATEGORY,如图,现在想取出分类数据后以树型展开并在下拉框中显示出来。


本来的方案是取出数据后在中间层对DataTable排序,格式字符串等放在一起操作的,后来感觉中间层负担太重,所以把排序放到了存储过程中。参考了SqlServer手册,终于完成了,分享一下吧。
存储过程代码如下:


本来的方案是取出数据后在中间层对DataTable排序,格式字符串等放在一起操作的,后来感觉中间层负担太重,所以把排序放到了存储过程中。参考了SqlServer手册,终于完成了,分享一下吧。
存储过程代码如下:
程序代码:
CREATE PROC SPMakeCatyTree
(@Child_node int)
As
SET NOCOUNT ON
--定义变量
DECLARE @lvl int--层次关系
DECLARE @title char(100)--分类名称
--生成临时表
CREATE TABLE #stack (Child_node int,Lvl int)
--生成目的表
CREATE TABLE #FileList(lvl int,CatyID int,CatyName char(100) )
--初始化数据
INSERT INTO #stack VALUES(@Child_node,0)
SELECT @Lvl = 0
--循环开始
WHILE @Lvl > -1
BEGIN
IF EXISTS(SELECT * FROM #stack WHERE Lvl = @Lvl)
--如果存在平辈选项
BEGIN
SELECT @Child_node = Child_node FROM #stack WHERE Lvl = @Lvl
--找到该条真实数据
SELECT @title = cname FROM b_category WHERE cateid = @Child_node
--保存辈分等级,原ID,分类名称
INSERT INTO #FileList VALUES(@Lvl, @Child_node, @title)
--删除临时表该条数据
DELETE FROM #stack WHERE Lvl = @Lvl AND Child_node = @Child_node
--向临时表插入儿子数据
INSERT INTO #stack SELECT cateid,@Lvl + 1 FROM b_category WHERE catepid = @Child_node
--如果以上语句执行-则儿子存在,辈分递增
IF @@ROWCOUNT > 0
SELECT @Lvl = @Lvl + 1
END
ELSE
--不存在平辈数据,返回父辈
SELECT @Lvl = @Lvl - 1
END
--清除初始化数据
DELETE FROM #FileList WHERE Lvl = 0
--取出排序后的数据
SELECT * FROM #FileList
GO
(@Child_node int)
As
SET NOCOUNT ON
--定义变量
DECLARE @lvl int--层次关系
DECLARE @title char(100)--分类名称
--生成临时表
CREATE TABLE #stack (Child_node int,Lvl int)
--生成目的表
CREATE TABLE #FileList(lvl int,CatyID int,CatyName char(100) )
--初始化数据
INSERT INTO #stack VALUES(@Child_node,0)
SELECT @Lvl = 0
--循环开始
WHILE @Lvl > -1
BEGIN
IF EXISTS(SELECT * FROM #stack WHERE Lvl = @Lvl)
--如果存在平辈选项
BEGIN
SELECT @Child_node = Child_node FROM #stack WHERE Lvl = @Lvl
--找到该条真实数据
SELECT @title = cname FROM b_category WHERE cateid = @Child_node
--保存辈分等级,原ID,分类名称
INSERT INTO #FileList VALUES(@Lvl, @Child_node, @title)
--删除临时表该条数据
DELETE FROM #stack WHERE Lvl = @Lvl AND Child_node = @Child_node
--向临时表插入儿子数据
INSERT INTO #stack SELECT cateid,@Lvl + 1 FROM b_category WHERE catepid = @Child_node
--如果以上语句执行-则儿子存在,辈分递增
IF @@ROWCOUNT > 0
SELECT @Lvl = @Lvl + 1
END
ELSE
--不存在平辈数据,返回父辈
SELECT @Lvl = @Lvl - 1
END
--清除初始化数据
DELETE FROM #FileList WHERE Lvl = 0
--取出排序后的数据
SELECT * FROM #FileList
GO
程序代码:
/// <summary>
/// 格式化树型样式
/// </summary>
/// <param name="dataset"></param>
/// <returns></returns>
public DataTable FormatDS(DataSet dataset)
{
DataTable dt = null;
if(dataset == null)
{
//空数据错误处理
return dt;
}
else
{
dt = dataset.Tables[0];
for(int i = 0; i < dt.Rows.Count; i++)
{
//根选项以"├"开始
if(Convert.ToInt32(dt.Rows[i][0]) == 1)
{
dt.Rows[i].BeginEdit();
dt.Rows[i][2]= "├" + dt.Rows[i][2];
dt.Rows[i].EndEdit();
}
else//非子孙选项样式
{
dt.Rows[i].BeginEdit();
dt.Rows[i][2]= "│" + CountBlank(Convert.ToInt32(dt.Rows[i][0])) + "├" + dt.Rows[i][2];
dt.Rows[i].EndEdit();
}
}
return dt;
}
}
/// <summary>
/// 打印指定空格数目
/// </summary>
/// <param name="ier">子孙辈分(分类深度)</param>
public string CountBlank(int ier)
{
string res = "";
//从孙子分类开始打印全角空格
while(ier > 2)
{
res += " ";
ier -= 1;
}
return res;
}
/// 格式化树型样式
/// </summary>
/// <param name="dataset"></param>
/// <returns></returns>
public DataTable FormatDS(DataSet dataset)
{
DataTable dt = null;
if(dataset == null)
{
//空数据错误处理
return dt;
}
else
{
dt = dataset.Tables[0];
for(int i = 0; i < dt.Rows.Count; i++)
{
//根选项以"├"开始
if(Convert.ToInt32(dt.Rows[i][0]) == 1)
{
dt.Rows[i].BeginEdit();
dt.Rows[i][2]= "├" + dt.Rows[i][2];
dt.Rows[i].EndEdit();
}
else//非子孙选项样式
{
dt.Rows[i].BeginEdit();
dt.Rows[i][2]= "│" + CountBlank(Convert.ToInt32(dt.Rows[i][0])) + "├" + dt.Rows[i][2];
dt.Rows[i].EndEdit();
}
}
return dt;
}
}
/// <summary>
/// 打印指定空格数目
/// </summary>
/// <param name="ier">子孙辈分(分类深度)</param>
public string CountBlank(int ier)
{
string res = "";
//从孙子分类开始打印全角空格
while(ier > 2)
{
res += " ";
ier -= 1;
}
return res;
}