none
数据库中树的实现 RRS feed

  • 常规讨论

  • 我想问一下各位同行在数据库中表示树结构时有什么高招
    在表设计和查询上有什么要注意的
    我的项目中的树很大10W~20w数据
    树的深度在20层一样
    大多树业务都要查询这个表示树的表
    2009年10月16日 10:12

全部回复

  • 在函数或储存过程中递归一下,或者使用公表with Common

    with MyCommon as
    (
          select *,AdvanceId BottomId from tAdvance 
          union all 
          select tAdvance.*,MyCommon.BottomId from tAdvance join Common on tAdvance.AdvanceId=Common.Advance_Id
    )
    select * from MyCommon where BottomId=1
    2009年10月16日 10:34
  • 数据库本身就是B+ Tree了,用传统的方式存放树结构反而性能较差。最好转换一下思维,比如论坛就是一个很好的例子,不是说bbs这种平板结构。
    想不想时已是想,不如不想都不想。
    2009年10月17日 5:37
    版主
  • 数据库本身就是B+ Tree了,用传统的方式存放树结构反而性能较差。最好转换一下思维,比如论坛就是一个很好的例子,不是说bbs这种平板结构。
    想不想时已是想,不如不想都不想。

    您能说的具体一点吗?
    或有什么这方面的资料
    谢谢
    2009年10月17日 7:42
  • 在SQL2008已经对树型的数据存储提供了数据类型(hierarchyid )支持
    但是对于大型的树性能不是很满意
    它利用的是路径的方法
    例如: 1.1.2.1.3.1或是ID.ID
    这种放到这个字段就会很大 这样在上面很难建立索引所以效率很差
    这次希望个位高人能给出好的建议
    2009年10月17日 7:51
  • 树形数据
    
    -- 树形数据层次显示处理示例
    --测试数据
    DECLARE @t TABLE(ID char(3),PID char(3),Name nvarchar(10))
    INSERT @t SELECT '001',NULL ,'山东省'
    UNION ALL SELECT '002','001','烟台市'
    UNION ALL SELECT '004','002','招远市'
    UNION ALL SELECT '003','001','青岛市'
    UNION ALL SELECT '005',NULL ,'四会市'
    UNION ALL SELECT '006','005','清远市'
    UNION ALL SELECT '007','006','小分市'
    
    --深度排序显示处理
    --生成每个节点的编码累计(相同当单编号法的编码)
    DECLARE @t_Level TABLE(ID char(3),Level int,Sort varchar(8000))
    DECLARE @Level int
    SET @Level=0
    INSERT @t_Level SELECT ID,@Level,ID
    FROM @t
    WHERE PID IS NULL
    WHILE @@ROWCOUNT>0
    BEGIN
        SET @Level=@Level+1
        INSERT @t_Level SELECT a.ID,@Level,b.Sort+a.ID
        FROM @t a,@t_Level b
        WHERE a.PID=b.ID
            AND b.Level=@Level-1
    END
    
    --显示结果
    SELECT SPACE(b.Level*2)+'|--'+a.Name
    FROM @t a,@t_Level b
    WHERE a.ID=b.ID
    ORDER BY b.Sort
    /*--结果
    |--山东省
      |--烟台市
        |--招远市
      |--青岛市
    |--四会市
      |--清远市
        |--小分市
    --*/
    
    
    
    --树形数据广度排序处理示例.
    --测试数据
    DECLARE @t TABLE(ID char(3),PID char(3),Name nvarchar(10))
    INSERT @t SELECT '001',NULL ,'山东省'
    UNION ALL SELECT '002','001','烟台市'
    UNION ALL SELECT '004','002','招远市'
    UNION ALL SELECT '003','001','青岛市'
    UNION ALL SELECT '005',NULL ,'四会市'
    UNION ALL SELECT '006','005','清远市'
    UNION ALL SELECT '007','006','小分市'
    
    --广度排序显示处理
    --生成每个节点的层次数据
    DECLARE @t_Level TABLE(ID char(3),Level int)
    DECLARE @Level int
    SET @Level=0
    INSERT @t_Level SELECT ID,@Level
    FROM @t
    WHERE PID IS NULL
    WHILE @@ROWCOUNT>0
    BEGIN
        SET @Level=@Level+1
        INSERT @t_Level SELECT a.ID,@Level
        FROM @t a,@t_Level b
        WHERE a.PID=b.ID
            AND b.Level=@Level-1
    END
    
    --显示结果
    SELECT a.*
    FROM @t a,@t_Level b
    WHERE a.ID=b.ID
    ORDER BY b.Level,b.ID
    /*--结果
    ID   PID  Name       
    ------- --------- ---------- 
    001  NULL 山东省
    005  NULL 四会市
    002  001   烟台市
    003  001   青岛市
    006  005   清远市
    004  002   招远市
    007  006   小分市
    --*/
    
    -- 树形数据深度排序处理示例(递归法)
    --测试数据
    CREATE TABLE tb(ID char(3),PID char(3),Name nvarchar(10))
    INSERT tb SELECT '001',NULL ,'山东省'
    UNION ALL SELECT '002','001','烟台市'
    UNION ALL SELECT '004','002','招远市'
    UNION ALL SELECT '003','001','青岛市'
    UNION ALL SELECT '005',NULL ,'四会市'
    UNION ALL SELECT '006','005','清远市'
    UNION ALL SELECT '007','006','小分市'
    GO
    
    --广度搜索排序函数
    CREATE FUNCTION f_Sort(@ID char(3)=NULL,@sort int=1)
    RETURNS @t_Level TABLE(ID char(3),sort int)
    AS
    BEGIN
        DECLARE tb CURSOR LOCAL
        FOR
        SELECT ID FROM tb
        WHERE PID=@ID
            OR(@ID IS NULL AND PID IS NULL)
        OPEN TB
        FETCH tb INTO @ID
        WHILE @@FETCH_STATUS=0
        BEGIN
            INSERT @t_Level VALUES(@ID,@sort)
            SET @sort=@sort+1
            IF @@NESTLEVEL<32 --如果递归层数未超过32层(递归最大允许32层)
            BEGIN
                --递归查找当前节点的子节点
                INSERT @t_Level SELECT * FROM f_Sort(@ID,@sort)
                SET @sort=@sort+@@ROWCOUNT  --排序号加上子节点个数
            END
            FETCH tb INTO @ID
        END
        RETURN
    END
    GO
    
    --显示结果
    SELECT a.*
    FROM tb a,f_Sort(DEFAULT,DEFAULT) b
    WHERE a.ID=b.ID
    ORDER BY b.sort
    /*--结果
    ID   PID   Name       
    ------ --------- ---------- 
    001  NULL 山东省
    002  001   烟台市
    004  002   招远市
    003  001   青岛市
    005  NULL 四会市
    006  005   清远市
    007  006   小分市
    --*/
    
    
    

    More: blog.csdn.net/happyflystone
    2009年10月19日 4:18