您所在的位置: 程序员家园 -> 家园博客 ->
 
在哪里摔倒
就在哪里自己爬起来

用户登录

查  找

最新评论

最新留言

常用网站

网易邮箱 GMAIL  

百度搜索 MSDN

霏凡软件 BT精品

影视帝国 射 手 网

电驴下载 全 库 网

友情连接

茄菲的窝 冰冰博客

枫叶飘零 玫  瑰

ACEN 云 豹 子

统  计



分级栏目管理的一种比较简单的数据结构
狼子 发表于 2008-4-25 18:03:00 阅读全文 | 回复(0) | 引用通告 | 编辑

栏目管理或者说目录管理、分类管理,很多地方都要用到,都说有无限级分类和有限级分类两种,就是,我觉得,有限和无限,是看你的列表要怎么出的

然后呢,栏目管理最主要要做的就是:部分列表、完整列表、分类排序、分类转移四个

最普通的有限级分类有两种方法:
1、使用serialNumber(序列号)记录层次,比如说下面的:

  001 计算机类书籍
    001001 语言学习类
     001001001 C#
     001001002 JAVA
     001001003 PB
    001002 数据结构类
    001003 数据库
  002 英语学习类书籍
    002001 双语书籍
    002002 原版书籍

  这种记录分类管理的办法,级数的限制是在serialNumber的长度,如果像上面的例子,每级3个数字,那每级最大就是999个分类,这种分类管理,我在用asp的时候一直使用,因为分类的数据量一般不会太大的,使用JavaScript就可以一次性用serialNumber排序用tree的样子显示出所有数据,这种方法我在这里有详细的例子:http://www.tiantiansoft.com/bbs/dispbbs.asp?BoardID=54&id=11465

2、使用父级的路径、全局次序号记录,比如说下面的:

  编号 分类名称  父级编号  父级路径  全局次序号
  1  计算机书籍  0      ,0,    1
  2  语言学习类  1      ,0,1,   2
  3  C#      1      ,0,1,2,  3
  4  PB      1      ,0,1,2,  4
  5  JAVA     1      ,0,1,2,  5

  这种记录分类的方法,级数的限制在你父级路径的长度,因为父级路径记录的是带分隔符的编号,编号的长度又不可以估计,所以最大的级数也不可以精确估计,这种方法我在后来用了ms sql数据库后一直使用,因为在ms sql数据库里可以使用存储过程,用存储过程管理父级路径很方便,比在asp里用代码管理serialNumber方便,显示的时候,也可以直接用treeview控件显示出来,在这里有详细例子:user1/9/archives/2007/3551.html

就是这两种管理分类的方法,在做分类的转移时,比较复杂

下面要说的这种方法,可以说是不限制级数的,也可以说限制了级数,问题就在我们怎么显示数据,这种方法是我这两天才搞的,方法是最老的方法,也是好多好多年前,知识最少的时候想到的第一种数据结构,一直没有使用这种方法,是因为栏目的列表问题

先看数据结构:

  CatalogID ParentID CatalogOrder CatalogName
  1     0     1      计算机书籍
  2     1     1      语言学习类
  3     2     1      C#
  4     2     2      JAVA
  5     2     3      PB
  6     1     2      数据结构类
  7     0     2      英语学习类书籍

  看上面的数据,关键就在CatalogOrder字段,这里记录的不是全局次序号,是同一个父级编号ParentID的同层次序号

说这种方法是无限级分类的,原因就是这种结构里,没有东西会控制分类,ParentID和CatalogOrder都是int型数据,我想不会有哪种分类,级数会超过ms sql里int型数据的最大值的

用这种数据结构,管理数据是很简单的,因为只需要管理两个字段,只要保证CatalogOrder字段在同一层里每个记录唯一就可以了,所以分类的排序、分类的转移,都变得很简单,分类列表呢,有两种办法

如果要在一个页面里,一次性显示出所有分类的列表,最容易想到的就是使用递归,如果是用tsql写存储过程递归,我想不出别的可以避开使用游标的办法,如果是在程序的代码里使用递归,我们就需要一次又一次的访问数据库了

在以前知识很少的时候,这种数据结构因为简单,所以很容易想到,就是,递归在那时候的知识里,是不懂的,所以也因为列不出列表就放弃了

这两天重新看这种方法,递归已经变得很简单,没什么好说了,就是自己调用自己,我要说的是另一种不使用递归的办法

下面我说这种办法,这种办法是借tsql的自定义函数通过ParentID和CatalogOrder获取serialNumber的值,然后呢,用serialNumber排序,先看我的自定义函数

CREATE  function dbo.a_Catalog_parentPath
   ( @CatalogID int )
returns varchar(100)
as
begin
   --返回指定@CatalogID的栏目的父级路径和次序
   declare @parentPath varchar(300), @oneLayerLen int
   select @parentPath = '', @oneLayerLen = 3
   while @CatalogID <> 0
      begin
        select @CatalogID = parentID,
              @parentPath = replace(space(@oneLayerLen - len(convert(varchar(10), CatalogOrder))), ' ', '0') + convert(varchar(10), CatalogOrder)
                          + @parentPath
          from A_CatalogCn
         where CatalogID = @CatalogID
      end
   return ( @parentPath )
end

再看显示完整列表的存储过程

CREATE proc a_Catalog_list() as
select CatalogID, parentID, dbo.a_Catalog_parentPath(CatalogID) as serialNumber,
       replace(space(len(dbo.a_Catalog_parentPath(CatalogID)) / 3 - 1), ' ', ' ') + '|-' + CatalogName as CatalogName
  from A_CatalogCn
 order by serialNumber, CatalogID

看自定义函数,我设置了

declare @parentPath varchar(300), @oneLayerLen int
select @parentPath = '', @oneLayerLen = 3

就是这两个值,把无限级分类的数据结构,变成有限级分类的数据结构了,这里返回的serialNumber是和第一种方法里的serialNumber是一样子的,001001002,所以长度是300,每层是3个字段,就控制了根目录最多100个,每层最多999个分类

就是,因为这两个都是定义在自定义存储过程里的,所以修改也比较方便,如果级数不够,随时都可以添加,所以我觉得,这种办法还是很方便的

这种办法的坏处是,为了得到serialNumber,我在自定义函数里使用了循环,每次都从当前记录一直取到他的父级,有点浪费资源

发表评论:

    昵称:
    密码:
    主页:
    标题:
Powered by Oblog.