精华内容
下载资源
问答
  • matlab开发-层次结构图像分割。该matlab代码实现了一个基于边缘的几何活动轮廓模型,无需重新初始
  • 层次贝叶斯模型

    2020-10-22 16:41:48
    层次贝叶斯模型是具有结构化层次的统计模型,它可以用来为复杂的统计问题建立层次模型从而避免参数过多导致的过拟合问题。 通过贝叶斯方法来估计后验分布的参数。 2 推断过程: 我们对层次贝叶斯推断的策略与一般...

    1 概念:

    层次贝叶斯模型是具有结构化层次的统计模型,它可以用来为复杂的统计问题建立层次模型从而避免参数过多导致的过拟合问题。

    通过贝叶斯方法来估计后验分布的参数。

    2 推断过程:

    我们对层次贝叶斯推断的策略与一般的多参数问题一样,但由于在实际中层次模型的参数很多,所以比较困难,在实际中我们很难画出联合后联合概率分布的图形。但是可以使用近似的基于仿真的方法.运用层次贝叶斯模型主要需要计算所有参赛在已知观察量下的条件后验概率,其推导过程主要包含三个步骤:

    1) 写出联合后验密度,p(θ, φ|y),其非正规化的形式是超先验分布p(φ),总体分布 p(θ|φ) 和似然函数p(y|θ) 的乘积。

    2), 在给定超参数φ 的情况下,确定θ 的条件后验密度,固定观测值y的情况下,它是φ 的函数,p(θ|φ, y)。

    3) 使用贝叶斯分析范例估计φ。 也就是要获取边缘后验分布,p(φ|y)。

    应用: 很多统计模型都有多个参数,这些参数也可以通过某种方式变成具有结构的问题,意味着这些参数的联合概率模型应当反应出它们之间的依赖关系。举个例子:在研究心脏病治疗效果的时候,医院j的存活率为θj,那么 估计θj 应当是相互联系的。我们可以看到使用先验分布把θj 当作一个总体分布的样本是很自然的事情,这样的应用有一个很关键的点是观测数据yij,其中观测的结果是在某些参数下的条件模型,这些参数称为超参数。 这样的层次模型可以帮助我们理解多参数问题,并且在寻找计算策略时提供重要帮助。

      实际上,简单的非层次模型可能并不适合层次数据,在很少参数的情况下,它们并不能准确适配大规模数据集,然而过多的参数则可能导致过拟合的问题. 相反层次模型有足够的参数来拟合数据,同时使用总体分布将参数的依赖结构话,从而避免过拟合问题。

    3 贝叶斯和层次贝叶斯的比较

    https://blog.csdn.net/lee813/article/details/53446560

     

     

    展开全文
  • 数据字典对在数据流中每一个命名的图形元素给予定义其内容有图形元素的名字别名或编号分类描述定义位置等等 3.Warnier是表示数据层次结构的一种图形工具以树形结构来描述数据结构还能指出某一类数据或某以数据...
  • 首先,基于人类驾驶认知的分层记忆机理,按照被处理信息由低到高的抽象层次,将环境认知分为环境目标感知和态势认知两大任务模块,提出层次化框架;然后,确定层次因子的拓扑结构并实现层次因子图模型,目标感知层具体...
  • 体系结构模型的形式语义用类型范畴图表来表示,态射合成被用来追踪构件模型之间的关联和映射,不同层次模型间的映射关系用态射和函子来形式描述.以此为基础,进一步分析了模型转换应保持的语义特性.范畴理论支持...
  • 在这项工作中,我们详细说明了Inert Higgs doublet模型的特定扩展的前景,在该模型中,通过完全可归一的方式通过辐射虚拟校正顺序生成SM层次结构,即无需添加任何不可归一的Yukawa项或软破坏算符 到标量势。...
  • 一般模型有:员工组织(树,层次结构);料表--BOM(有向);道路系统(无向循环) <br />1.迭代/递归 迭代可以迭代的一个节点,也可以迭代一个层次.后者比前者要快很多. 实现方法:SQL2000通过...

    在RDBMS中操作 图 树 层次结构 等特殊的数据结构时,我们通常采用2个主要方法:
    1.基于迭代/递归

    2.具体化描述数据结构的附加信息。
    一般模型有:员工组织图(树,层次结构);料表--BOM(有向图);道路系统(无向循环图)


    1.迭代/递归
    迭代可以迭代图的一个节点,也可以迭代一个层次.后者比前者要快很多.
    实现方法:SQL2000通过UDF(用户自定义函数),SQL2005使用CTE。

    a.下属问题(通俗说,求子节点)
    --这里我使用书上的员工表(表内容如下)
    view plaincopy to clipboardprint?
     SET NOCOUNT ON;  
    USE tempdb;  
    GO  
    IF OBJECT_ID('dbo.Employees') IS NOT NULL  
      DROP TABLE dbo.Employees;  
    GO  
    CREATE TABLE dbo.Employees  
    (  
      empid   INT         NOT NULL PRIMARY KEY,  
      mgrid   INT         NULL     REFERENCES dbo.Employees,  
      empname VARCHAR(25) NOT NULL,  
      salary  MONEY       NOT NULL,  
      CHECK (empid <> mgrid)  
    );  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(1, NULL, 'David', $10000.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(2, 1, 'Eitan', $7000.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(3, 1, 'Ina', $7500.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(4, 2, 'Seraph', $5000.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(5, 2, 'Jiru', $5500.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(6, 2, 'Steve', $4500.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(7, 3, 'Aaron', $5000.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(8, 5, 'Lilach', $3500.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(9, 7, 'Rita', $3000.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(10, 5, 'Sean', $3000.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(11, 7, 'Gabriel', $3000.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(12, 9, 'Emilia' , $2000.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(13, 9, 'Michael', $2000.00);  
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)  
      VALUES(14, 9, 'Didi', $1500.00);  
    --创建索引  
    CREATE UNIQUE INDEX idx_unc_mgrid_empid ON dbo.Employees(mgrid, empid);  
    go 
     SET NOCOUNT ON;
    USE tempdb;
    GO
    IF OBJECT_ID('dbo.Employees') IS NOT NULL
      DROP TABLE dbo.Employees;
    GO
    CREATE TABLE dbo.Employees
    (
      empid   INT         NOT NULL PRIMARY KEY,
      mgrid   INT         NULL     REFERENCES dbo.Employees,
      empname VARCHAR(25) NOT NULL,
      salary  MONEY       NOT NULL,
      CHECK (empid <> mgrid)
    );
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(1, NULL, 'David', $10000.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(2, 1, 'Eitan', $7000.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(3, 1, 'Ina', $7500.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(4, 2, 'Seraph', $5000.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(5, 2, 'Jiru', $5500.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(6, 2, 'Steve', $4500.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(7, 3, 'Aaron', $5000.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(8, 5, 'Lilach', $3500.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(9, 7, 'Rita', $3000.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(10, 5, 'Sean', $3000.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(11, 7, 'Gabriel', $3000.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(12, 9, 'Emilia' , $2000.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(13, 9, 'Michael', $2000.00);
    INSERT INTO dbo.Employees(empid, mgrid, empname, salary)
      VALUES(14, 9, 'Didi', $1500.00);
    --创建索引
    CREATE UNIQUE INDEX idx_unc_mgrid_empid ON dbo.Employees(mgrid, empid);
    go


    --SQL2000 udf方法:

    view plaincopy to clipboardprint?
    IF OBJECT_ID('dbo.fn_subordinates1') IS NOT NULL  
      DROP FUNCTION dbo.fn_subordinates1;  
    GO  
    CREATE FUNCTION dbo.fn_subordinates1(@root AS INT)   
    RETURNS @Subs TABLE  
    (  
      empid INT NOT NULL PRIMARY KEY NONCLUSTERED,  
      lvl   INT NOT NULL,  
      UNIQUE CLUSTERED(lvl, empid)    
    )  
    AS  
    begin   
    declare @lv int   
    set @lv=0 
    insert @Subs values(@root,@lv)  
    while @@rowcount>0 
    begin   
     set @lv=@Lv+1;  
     insert @subs  
     select b.empid ,@Lv  
     from @subs a join dbo.Employees b on a.empid=b.mgrid and
    lvl=@lv-1 
    end  
    return;  
    end   
    go  
    SELECT empid, lvl FROM dbo.fn_subordinates1(3) AS S;  
     
      
    IF OBJECT_ID('dbo.fn_subordinates1') IS NOT NULL
      DROP FUNCTION dbo.fn_subordinates1;
    GO
    CREATE FUNCTION dbo.fn_subordinates1(@root AS INT)
    RETURNS @Subs TABLE
    (
      empid INT NOT NULL PRIMARY KEY NONCLUSTERED,
      lvl   INT NOT NULL,
      UNIQUE CLUSTERED(lvl, empid) 
    )
    AS
    begin
    declare @lv int
    set @lv=0
    insert @Subs values(@root,@lv)
    while @@rowcount>0
    begin
     set @lv=@Lv+1;
     insert @subs
     select b.empid ,@Lv
     from @subs a join dbo.Employees b on a.empid=b.mgrid and
    lvl=@lv-1
    end
    return;
    end
    go
    SELECT empid, lvl FROM dbo.fn_subordinates1(3) AS S;

     
     

     

    --SQL2005 CTE

     

    view plaincopy to clipboardprint?
    DECLARE @root AS INT;  
    SET @root = 3;  
    WITH SubsCTE  
    AS  
    (  
      -- Anchor member returns root node  
      SELECT empid, empname, 0 AS lvl  
      FROM dbo.Employees  
      WHERE empid = @root  
     
      UNION ALL  
     
      -- Recursive member returns next level of children  
      SELECT C.empid, C.empname, P.lvl + 1  
      FROM SubsCTE AS P  
        JOIN dbo.Employees AS C  
          ON C.mgrid = P.empid  
    )  
    SELECT * FROM SubsCTE; 
    DECLARE @root AS INT;
    SET @root = 3;
    WITH SubsCTE
    AS
    (
      -- Anchor member returns root node
      SELECT empid, empname, 0 AS lvl
      FROM dbo.Employees
      WHERE empid = @root

      UNION ALL

      -- Recursive member returns next level of children
      SELECT C.empid, C.empname, P.lvl + 1
      FROM SubsCTE AS P
        JOIN dbo.Employees AS C
          ON C.mgrid = P.empid
    )
    SELECT * FROM SubsCTE;
     

     

     

    --查询结果
    view plaincopy to clipboardprint?
    /* 
    empid       empname                   lvl 
    ----------- ------------------------- ----------- 
    3           Ina                       0 
    7           Aaron                     1 
    9           Rita                      2 
    11          Gabriel                   2 
    12          Emilia                    3 
    13          Michael                   3 
    14          Didi                      3 
     
    */ 
    /*
    empid       empname                   lvl
    ----------- ------------------------- -----------
    3           Ina                       0
    7           Aaron                     1
    9           Rita                      2
    11          Gabriel                   2
    12          Emilia                    3
    13          Michael                   3
    14          Didi                      3

    */
     


    ---------------如果需要限制递归的层数------------


    --SQL2000

    view plaincopy to clipboardprint?
    IF OBJECT_ID('dbo.fn_subordinates2') IS NOT NULL  
      DROP FUNCTION dbo.fn_subordinates2;  
    GO  
    CREATE FUNCTION dbo.fn_subordinates2  
      (@root AS INT, @maxlevels AS INT = NULL) RETURNS @Subs TABLE  
    (  
      empid INT NOT NULL PRIMARY KEY NONCLUSTERED,  
      lvl   INT NOT NULL,  
      UNIQUE CLUSTERED(lvl, empid)    
    )  
    AS  
    BEGIN  
      DECLARE @lvl AS INT;  
      SET @lvl = 0;              
      -- 如果@maxlevels输入的是NULL,把他变为最大的INT类型  
     SET @maxlevels = COALESCE(@maxlevels, 2147483647);  
      INSERT INTO @Subs(empid, lvl)  
        SELECT empid, @lvl FROM dbo.Employees WHERE empid = @root;  
     
      WHILE @@rowcount > 0           
        AND @lvl < @maxlevels       -- 这里注意加一个小于最大的递归数的条件,是小于 不是小于等于   
      BEGIN  
        SET @lvl = @lvl + 1;          
     
        INSERT INTO @Subs(empid, lvl)  
          SELECT C.empid, @lvl               --这里跟上面处理都一样  
          FROM @Subs AS P             
            JOIN dbo.Employees AS C   
              ON P.lvl = @lvl - 1    
              AND C.mgrid = P.empid;  
      END  
     
      RETURN;  
    END  
    GO  
    SELECT empid, lvl  
    FROM dbo.fn_subordinates2(3, NULL) AS S; 
    IF OBJECT_ID('dbo.fn_subordinates2') IS NOT NULL
      DROP FUNCTION dbo.fn_subordinates2;
    GO
    CREATE FUNCTION dbo.fn_subordinates2
      (@root AS INT, @maxlevels AS INT = NULL) RETURNS @Subs TABLE
    (
      empid INT NOT NULL PRIMARY KEY NONCLUSTERED,
      lvl   INT NOT NULL,
      UNIQUE CLUSTERED(lvl, empid) 
    )
    AS
    BEGIN
      DECLARE @lvl AS INT;
      SET @lvl = 0;           
      -- 如果@maxlevels输入的是NULL,把他变为最大的INT类型
     SET @maxlevels = COALESCE(@maxlevels, 2147483647);
      INSERT INTO @Subs(empid, lvl)
        SELECT empid, @lvl FROM dbo.Employees WHERE empid = @root;

      WHILE @@rowcount > 0        
        AND @lvl < @maxlevels       -- 这里注意加一个小于最大的递归数的条件,是小于 不是小于等于
      BEGIN
        SET @lvl = @lvl + 1;       

        INSERT INTO @Subs(empid, lvl)
          SELECT C.empid, @lvl               --这里跟上面处理都一样
          FROM @Subs AS P          
            JOIN dbo.Employees AS C
              ON P.lvl = @lvl - 1 
              AND C.mgrid = P.empid;
      END

      RETURN;
    END
    GO
    SELECT empid, lvl
    FROM dbo.fn_subordinates2(3, NULL) AS S;

     

    --查询结果

    view plaincopy to clipboardprint?
    /* 
    empid       lvl 
    ----------- ----------- 
    3           0 
    7           1 
    9           2 
    11          2 
    12          3 
    13          3 
    14          3 
    */ 
    ----- 
    /*
    empid       lvl
    ----------- -----------
    3           0
    7           1
    9           2
    11          2
    12          3
    13          3
    14          3
    */
    -----


    SELECT empid, lvl
    FROM dbo.fn_subordinates2(2, NULL) AS S;

    view plaincopy to clipboardprint?
    /* 
    empid       lvl 
    ----------- ----------- 
    2           0 
    4           1 
    5           1 
    6           1 
    8           2 
    10          2 
    */ 
    /*
    empid       lvl
    ----------- -----------
    2           0
    4           1
    5           1
    6           1
    8           2
    10          2
    */


    PS:这里控制返回的层数 你当然可以用最开始的方法,然后再筛选语句里控制层数
     如SELECT empid, lvl FROM dbo.fn_subordinates1(3) AS S where lvl<3;  但是控制本身的递归只能在UDF里面了
     
     --sql2005方法类似


    view plaincopy to clipboardprint?
     WITH SubsCTE  
    AS  
    (  
      SELECT empid, empname, 0 AS lvl  
      FROM dbo.Employees  
      WHERE empid = @root  
      UNION ALL  
     
      SELECT C.empid, C.empname, P.lvl + 1  
      FROM SubsCTE AS P  
        JOIN dbo.Employees AS C  
          ON C.mgrid = P.empid  
          AND P.lvl < @maxlevels -- 这里控制递归数  
    )  
    SELECT * FROM SubsCTE; 
     WITH SubsCTE
    AS
    (
      SELECT empid, empname, 0 AS lvl
      FROM dbo.Employees
      WHERE empid = @root
      UNION ALL

      SELECT C.empid, C.empname, P.lvl + 1
      FROM SubsCTE AS P
        JOIN dbo.Employees AS C
          ON C.mgrid = P.empid
          AND P.lvl < @maxlevels -- 这里控制递归数
    )
    SELECT * FROM SubsCTE;
     

    --还有一种偏方:但是不推荐 虽然结果正确 但是会报错
    view plaincopy to clipboardprint?
    WITH SubsCTE  
    AS  
    (  
      SELECT empid, empname, 0 AS lvl  
      FROM dbo.Employees  
      WHERE empid = @root  
     
      UNION ALL  
     
      SELECT C.empid, C.empname, P.lvl + 1  
      FROM SubsCTE AS P  
        JOIN dbo.Employees AS C  
          ON C.mgrid = P.empid  
    )  
    SELECT * FROM SubsCTE  
    OPTION (MAXRECURSION 2);--就是这里的MAXRECURSION 控制递归 
    WITH SubsCTE
    AS
    (
      SELECT empid, empname, 0 AS lvl
      FROM dbo.Employees
      WHERE empid = @root

      UNION ALL

      SELECT C.empid, C.empname, P.lvl + 1
      FROM SubsCTE AS P
        JOIN dbo.Employees AS C
          ON C.mgrid = P.empid
    )
    SELECT * FROM SubsCTE
    OPTION (MAXRECURSION 2);--就是这里的MAXRECURSION 控制递归

     

    --查询结果

    view plaincopy to clipboardprint?
     /* 
     empid       empname                   lvl 
    ----------- ------------------------- ----------- 
    3           Ina                       0 
    7           Aaron                     1 
    9           Rita                      2 
    11          Gabriel                   2 
    消息 530,级别 16,状态 1,第 4 行 
    语句被终止。完成执行语句前已用完最大递归 2。 
     */ 
     /*
     empid       empname                   lvl
    ----------- ------------------------- -----------
    3           Ina                       0
    7           Aaron                     1
    9           Rita                      2
    11          Gabriel                   2
    消息 530,级别 16,状态 1,第 4 行
    语句被终止。完成执行语句前已用完最大递归 2。
     */
     


    b.祖先(通俗说:求父节点)
    其实思路跟子节点差不多


    --SQL2000

     

    view plaincopy to clipboardprint?
    IF OBJECT_ID('dbo.fn_managers') IS NOT NULL  
      DROP FUNCTION dbo.fn_managers;  
    GO  
    CREATE FUNCTION dbo.fn_managers  
    (@empid AS INT, @maxlevels AS INT = NULL) RETURNS @Mgrs TABLE  
    (  
      empid INT NOT NULL PRIMARY KEY,  
      lvl   INT NOT NULL  
    )  
    AS  
    BEGIN  
      IF NOT EXISTS(SELECT * FROM dbo.Employees WHERE empid = @empid) --这里判断是否存在经理,不存在 马上返回  
        RETURN;  
     
      DECLARE @lvl AS INT,@mgrid int ;  
      SET @lvl = 0;    
      set @mgrid=@empid  --赋值给@mgrid 我这是为了更加清楚变量的意思 其实不用这个@Mgrid变量的            
     
      -- 如果@maxlevels输入的是NULL,把他变为最大的INT类型  
      SET @maxlevels = COALESCE(@maxlevels, 2147483647);  
     
      WHILE  @lvl <= @maxlevels and @mgrid is not null     --注意这里是小于等于 而且新插入的经理不可以为NULL,为null说明是老大了  
      BEGIN  
     --插入当前经理  
     INSERT INTO @Mgrs(empid, lvl) VALUES(@mgrid, @lvl); --这里第一次插入是自己,后面就是各自的经理了  
        SET @lvl = @lvl + 1;          
        --获得下一个级别的经理  
        SET @mgrid = (SELECT mgrid FROM dbo.Employees  
                      WHERE empid = @mgrid);  
        
      END  
     
      RETURN;  
    END  
    GO  
    SELECT empid, lvl  
    FROM dbo.fn_managers(8, NULL) AS M; 
    IF OBJECT_ID('dbo.fn_managers') IS NOT NULL
      DROP FUNCTION dbo.fn_managers;
    GO
    CREATE FUNCTION dbo.fn_managers
    (@empid AS INT, @maxlevels AS INT = NULL) RETURNS @Mgrs TABLE
    (
      empid INT NOT NULL PRIMARY KEY,
      lvl   INT NOT NULL
    )
    AS
    BEGIN
      IF NOT EXISTS(SELECT * FROM dbo.Employees WHERE empid = @empid) --这里判断是否存在经理,不存在 马上返回
        RETURN;

      DECLARE @lvl AS INT,@mgrid int ;
      SET @lvl = 0; 
      set @mgrid=@empid  --赋值给@mgrid 我这是为了更加清楚变量的意思 其实不用这个@Mgrid变量的         

      -- 如果@maxlevels输入的是NULL,把他变为最大的INT类型
      SET @maxlevels = COALESCE(@maxlevels, 2147483647);

      WHILE  @lvl <= @maxlevels and @mgrid is not null     --注意这里是小于等于 而且新插入的经理不可以为NULL,为null说明是老大了
      BEGIN
     --插入当前经理
     INSERT INTO @Mgrs(empid, lvl) VALUES(@mgrid, @lvl); --这里第一次插入是自己,后面就是各自的经理了
        SET @lvl = @lvl + 1;       
        --获得下一个级别的经理
        SET @mgrid = (SELECT mgrid FROM dbo.Employees
                      WHERE empid = @mgrid);
     
      END

      RETURN;
    END
    GO
    SELECT empid, lvl
    FROM dbo.fn_managers(8, NULL) AS M;

     

    --查询结果

    view plaincopy to clipboardprint?
    /* 
    empid       lvl 
    ----------- ----------- 
    1           3 
    2           2 
    5           1 
    8           0 
     
    */ 
    /*
    empid       lvl
    ----------- -----------
    1           3
    2           2
    5           1
    8           0

    */
     


    SELECT empid, lvl
    FROM dbo.fn_managers(8, 2) AS M;
    view plaincopy to clipboardprint?
    /* 
    empid       lvl 
    ----------- ----------- 
    2           2 
    5           1 
    8           0 
    */ 
    /*
    empid       lvl
    ----------- -----------
    2           2
    5           1
    8           0
    */

     

    --sql2005


    view plaincopy to clipboardprint?
    DECLARE @empid AS INT, @maxlevels AS INT;  
    SET @empid = 8;  
    SET @maxlevels = 2;  
     
    WITH MgrsCTE  
    AS  
    (  
      SELECT empid, mgrid, empname, 0 AS lvl  
      FROM dbo.Employees  
      WHERE empid = @empid  
     
      UNION ALL  
     
      SELECT P.empid, P.mgrid, P.empname, C.lvl + 1  
      FROM MgrsCTE AS C  
        JOIN dbo.Employees AS P  
          ON C.mgrid = P.empid  
          AND C.lvl < @maxlevels--限制递归数...  
    )  
    SELECT * FROM MgrsCTE; 
    DECLARE @empid AS INT, @maxlevels AS INT;
    SET @empid = 8;
    SET @maxlevels = 2;

    WITH MgrsCTE
    AS
    (
      SELECT empid, mgrid, empname, 0 AS lvl
      FROM dbo.Employees
      WHERE empid = @empid

      UNION ALL

      SELECT P.empid, P.mgrid, P.empname, C.lvl + 1
      FROM MgrsCTE AS C
        JOIN dbo.Employees AS P
          ON C.mgrid = P.empid
          AND C.lvl < @maxlevels--限制递归数...
    )
    SELECT * FROM MgrsCTE;
     

    C.层次显示

     

    --SQL2000,思路跟下属问题一模一样 只是多了个PATH
    view plaincopy to clipboardprint?
    IF OBJECT_ID('dbo.fn_subordinates3') IS NOT NULL  
      DROP FUNCTION dbo.fn_subordinates3;  
    GO  
    CREATE FUNCTION dbo.fn_subordinates3  
      (@root AS INT, @maxlevels AS INT = NULL) RETURNS @Subs TABLE  
    (  
      empid INT          NOT NULL PRIMARY KEY NONCLUSTERED,  
      lvl   INT          NOT NULL,  
      path  VARCHAR(900) NOT NULL  
      UNIQUE CLUSTERED(lvl, empid)   
    )  
    AS  
    BEGIN  
      DECLARE @lvl AS INT;  
      SET @lvl = 0;                  
     
      SET @maxlevels = COALESCE(@maxlevels, 2147483647);  
     
     
      INSERT INTO @Subs(empid, lvl, path)  
        SELECT empid, @lvl, CAST(empid AS VARCHAR(100))--ZHU YI ZHE LI   
        FROM dbo.Employees   
        WHERE empid = @root;  
     
      WHILE @@rowcount > 0            
        AND @lvl < @maxlevels         
      BEGIN  
        SET @lvl = @lvl + 1;         
     
     
        INSERT INTO @Subs(empid, lvl, path)  
          SELECT C.empid, @lvl,  
            P.path +'-'+ CAST(C.empid AS VARCHAR(100)) --和上面类型保持一致  
          FROM @Subs AS P             
            JOIN dbo.Employees AS C   
              ON P.lvl = @lvl - 1    
              AND C.mgrid = P.empid;  
      END  
     
      RETURN;  
    END  
    GO 
    IF OBJECT_ID('dbo.fn_subordinates3') IS NOT NULL
      DROP FUNCTION dbo.fn_subordinates3;
    GO
    CREATE FUNCTION dbo.fn_subordinates3
      (@root AS INT, @maxlevels AS INT = NULL) RETURNS @Subs TABLE
    (
      empid INT          NOT NULL PRIMARY KEY NONCLUSTERED,
      lvl   INT          NOT NULL,
      path  VARCHAR(900) NOT NULL
      UNIQUE CLUSTERED(lvl, empid)
    )
    AS
    BEGIN
      DECLARE @lvl AS INT;
      SET @lvl = 0;               

      SET @maxlevels = COALESCE(@maxlevels, 2147483647);


      INSERT INTO @Subs(empid, lvl, path)
        SELECT empid, @lvl, CAST(empid AS VARCHAR(100))--ZHU YI ZHE LI
        FROM dbo.Employees
        WHERE empid = @root;

      WHILE @@rowcount > 0         
        AND @lvl < @maxlevels      
      BEGIN
        SET @lvl = @lvl + 1;      


        INSERT INTO @Subs(empid, lvl, path)
          SELECT C.empid, @lvl,
            P.path +'-'+ CAST(C.empid AS VARCHAR(100)) --和上面类型保持一致
          FROM @Subs AS P          
            JOIN dbo.Employees AS C
              ON P.lvl = @lvl - 1 
              AND C.mgrid = P.empid;
      END

      RETURN;
    END
    GO

     

    --这里的显示分2种
    --显示1
    select empid ,pos=REPLICATE('-',lvl)+rtrim(empid)
    FROM dbo.fn_subordinates3(1, NULL) AS S
    ORDER BY PATH
    view plaincopy to clipboardprint?
    /* 
    empid       pos 
    ----------- ------------ 
    1           1 
    2           -2 
    4           --4 
    5           --5 
    10          ---10 
    8           ---8 
    6           --6 
    3           -3 
    7           --7 
    11          ---11 
    9           ---9 
    12          ----12 
    13          ----13 
    14          ----14 
    */ 
    /*
    empid       pos
    ----------- ------------
    1           1
    2           -2
    4           --4
    5           --5
    10          ---10
    8           ---8
    6           --6
    3           -3
    7           --7
    11          ---11
    9           ---9
    12          ----12
    13          ----13
    14          ----14
    */


    --还有一种
    SELECT empid,  path
    FROM dbo.fn_subordinates3(1, NULL) AS S
    ORDER BY PATH
    view plaincopy to clipboardprint?
    /* 
    empid       path 
    ----------- ---------------- 
    1           1 
    2           1-2 
    4           1-2-4 
    5           1-2-5 
    10          1-2-5-10 
    8           1-2-5-8 
    6           1-2-6 
    3           1-3 
    7           1-3-7 
    11          1-3-7-11 
    9           1-3-7-9 
    12          1-3-7-9-12 
    13          1-3-7-9-13 
    14          1-3-7-9-14 
    */ 
    /*
    empid       path
    ----------- ----------------
    1           1
    2           1-2
    4           1-2-4
    5           1-2-5
    10          1-2-5-10
    8           1-2-5-8
    6           1-2-6
    3           1-3
    7           1-3-7
    11          1-3-7-11
    9           1-3-7-9
    12          1-3-7-9-12
    13          1-3-7-9-13
    14          1-3-7-9-14
    */

    --当然上面的显示方式还很多,自己可以控制 比如不加ORDER 就可以排出不一样的

     

    --SQL2005


    view plaincopy to clipboardprint?
    DECLARE @root AS INT;  
    SET @root = 1;  
     
    WITH SubsCTE  
    AS  
    (  
      SELECT empid, empname, 0 AS lvl,  
        -- Path of root = '.' + empid + '.' 
        CAST(CAST(empid AS VARCHAR(10))   
             AS VARCHAR(MAX)) AS path  
      FROM dbo.Employees  
      WHERE empid = @root  
     
      UNION ALL  
     
      SELECT C.empid, C.empname, P.lvl + 1,  
     
        CAST(P.path+'-' + CAST(C.empid AS VARCHAR(10))   
             AS VARCHAR(MAX)) AS path  
      FROM SubsCTE AS P  
        JOIN dbo.Employees AS C  
          ON C.mgrid = P.empid  
    )  
    SELECT empid, REPLICATE(' | ', lvl) + empname AS empname  
    FROM SubsCTE  
    ORDER BY path 
    DECLARE @root AS INT;
    SET @root = 1;

    WITH SubsCTE
    AS
    (
      SELECT empid, empname, 0 AS lvl,
        -- Path of root = '.' + empid + '.'
        CAST(CAST(empid AS VARCHAR(10))
             AS VARCHAR(MAX)) AS path
      FROM dbo.Employees
      WHERE empid = @root

      UNION ALL

      SELECT C.empid, C.empname, P.lvl + 1,

        CAST(P.path+'-' + CAST(C.empid AS VARCHAR(10))
             AS VARCHAR(MAX)) AS path
      FROM SubsCTE AS P
        JOIN dbo.Employees AS C
          ON C.mgrid = P.empid
    )
    SELECT empid, REPLICATE(' | ', lvl) + empname AS empname
    FROM SubsCTE
    ORDER BY path
     ;

    --结果查询

    view plaincopy to clipboardprint?
    /* 
    empid       empname 
    ----------- ------------------------- 
    1           David 
    2            | Eitan 
    4            |  | Seraph 
    5            |  | Jiru 
    10           |  |  | Sean 
    8            |  |  | Lilach 
    6            |  | Steve 
    3            | Ina 
    7            |  | Aaron 
    11           |  |  | Gabriel 
    9            |  |  | Rita 
    12           |  |  |  | Emilia 
    13           |  |  |  | Michael 
    14           |  |  |  | Didi 
     
    */   
     
                   
     
      
    /*
    empid       empname
    ----------- -------------------------
    1           David
    2            | Eitan
    4            |  | Seraph
    5            |  | Jiru
    10           |  |  | Sean
    8            |  |  | Lilach
    6            |  | Steve
    3            | Ina
    7            |  | Aaron
    11           |  |  | Gabriel
    9            |  |  | Rita
    12           |  |  |  | Emilia
    13           |  |  |  | Michael
    14           |  |  |  | Didi

    */

                

     
     

    D.检测循环中异常
    说白了 就是检查表里有没出现1-2-4-1这种头接尾的圈.这在现实中是不可能的.一个经理部可能是它手下的手下.-- ||
    我们对表做手脚,把老大的经理改成是它的一个员工
    view plaincopy to clipboardprint?
    UPDATE dbo.Employees SET mgrid = 14 WHERE empid = 1;  
    DECLARE @root AS INT;  
    SET @root = 1;  
     
    WITH SubsCTE  
    AS  
    (  
      SELECT empid, empname, 0 AS lvl,  
        CAST( CAST(empid AS VARCHAR(10))  
             AS VARCHAR(MAX)) AS path,  
        -- 第一层是不会出现圈圈的  
        0 AS cycle --0表示没有圈 1表示出现圈  
      FROM dbo.Employees  
      WHERE empid = @root  
     
      UNION ALL  
     
      SELECT C.empid, C.empname, P.lvl + 1,  
        CAST(P.path + '-'+CAST(C.empid AS VARCHAR(10))   
             AS VARCHAR(MAX)) AS path,  
        -- 这里需要检查  
        CASE WHEN P.path LIKE '%' + CAST(C.empid AS VARCHAR(10)) + '%' 
          THEN 1 ELSE 0 END  
      FROM SubsCTE AS P  
        JOIN dbo.Employees AS C  
          ON C.mgrid = P.empid  
       where p.cycle=0 --保证不会继续在错误的地方继续循环下去  
    )  
    SELECT empid, empname, cycle, path  
    FROM SubsCTE  
    where cycle=1 
    UPDATE dbo.Employees SET mgrid = 14 WHERE empid = 1;
    DECLARE @root AS INT;
    SET @root = 1;

    WITH SubsCTE
    AS
    (
      SELECT empid, empname, 0 AS lvl,
        CAST( CAST(empid AS VARCHAR(10))
             AS VARCHAR(MAX)) AS path,
        -- 第一层是不会出现圈圈的
        0 AS cycle --0表示没有圈 1表示出现圈
      FROM dbo.Employees
      WHERE empid = @root

      UNION ALL

      SELECT C.empid, C.empname, P.lvl + 1,
        CAST(P.path + '-'+CAST(C.empid AS VARCHAR(10))
             AS VARCHAR(MAX)) AS path,
        -- 这里需要检查
        CASE WHEN P.path LIKE '%' + CAST(C.empid AS VARCHAR(10)) + '%'
          THEN 1 ELSE 0 END
      FROM SubsCTE AS P
        JOIN dbo.Employees AS C
          ON C.mgrid = P.empid
       where p.cycle=0 --保证不会继续在错误的地方继续循环下去
    )
    SELECT empid, empname, cycle, path
    FROM SubsCTE
    where cycle=1

     

    --查询结果

    view plaincopy to clipboardprint?
    /* 
    empid       empname                   cycle       path 
    ----------- ------------------------- ----------- ------------------ 
    1           David                     1           1-3-7-9-14-1 
     
    */ 
    /*
    empid       empname                   cycle       path
    ----------- ------------------------- ----------- ------------------
    1           David                     1           1-3-7-9-14-1

    */

     
    --这样管理员可以轻易找到那个错误的地方.
    改过来:UPDATE dbo.Employees SET mgrid = NULL WHERE empid = 1;

    2.具体化路径
    这里就是新增加2列,一列是级别 一列是节点路径,这样可以避免每次都去计算.
    2个优点:不需要递归,只需要基于集合 ;查询可以使用到路径索引

    a.维护数据


    1.添加不管理员工的员工
    view plaincopy to clipboardprint?
    SET NOCOUNT ON;  
    USE tempdb;  
    GO  
    IF OBJECT_ID('dbo.Employees') IS NOT NULL  
      DROP TABLE dbo.Employees;  
    GO  
    CREATE TABLE dbo.Employees  
    (  
      empid   INT          NOT NULL PRIMARY KEY NONCLUSTERED,  
      mgrid   INT          NULL     REFERENCES dbo.Employees,  
      empname VARCHAR(25)  NOT NULL,  
      salary  MONEY        NOT NULL,  
      lvl     INT          NOT NULL,  
      path    VARCHAR(900) NOT NULL UNIQUE CLUSTERED  
    );  
    CREATE UNIQUE INDEX idx_unc_mgrid_empid ON dbo.Employees(mgrid, empid);  
    GO  
    IF OBJECT_ID('dbo.usp_insertemp') IS NOT NULL  
      DROP PROC dbo.usp_insertemp;  
    GO  
    CREATE PROC dbo.usp_insertemp  
      @empid   INT,  
      @mgrid   INT,  
      @empname VARCHAR(25),  
      @salary  MONEY  
    AS  
     
    SET NOCOUNT ON;  
     
    -- 如果插入的是一个没有经理的老大  
    IF @mgrid IS NULL  
      INSERT INTO dbo.Employees(empid, mgrid, empname, salary, lvl, path)  
        VALUES(@empid, @mgrid, @empname, @salary,  
          0,  CAST(@empid AS VARCHAR(10)));  
    --插入有经理的小弟  
    ELSE  
      INSERT INTO dbo.Employees(empid, mgrid, empname, salary, lvl, path)  
        SELECT @empid, @mgrid, @empname, @salary,  
          lvl + 1, path +'-'+ CAST(@empid AS VARCHAR(10))   
        FROM dbo.Employees  
        WHERE empid = @mgrid;  
    GO  
     
    EXEC dbo.usp_insertemp  
      @empid = 1, @mgrid = NULL, @empname = 'David', @salary = $10000.00;  
    EXEC dbo.usp_insertemp  
      @empid = 2, @mgrid = 1, @empname = 'Eitan', @salary = $7000.00;  
    EXEC dbo.usp_insertemp  
      @empid = 3, @mgrid = 1, @empname = 'Ina', @salary = $7500.00;  
    EXEC dbo.usp_insertemp  
      @empid = 4, @mgrid = 2, @empname = 'Seraph', @salary = $5000.00;  
    EXEC dbo.usp_insertemp  
      @empid = 5, @mgrid = 2, @empname = 'Jiru', @salary = $5500.00;  
    EXEC dbo.usp_insertemp  
      @empid = 6, @mgrid = 2, @empname = 'Steve', @salary = $4500.00;  
    EXEC dbo.usp_insertemp  
      @empid = 7, @mgrid = 3, @empname = 'Aaron', @salary = $5000.00;  
    EXEC dbo.usp_insertemp  
      @empid = 8, @mgrid = 5, @empname = 'Lilach', @salary = $3500.00;  
    EXEC dbo.usp_insertemp  
      @empid = 9, @mgrid = 7, @empname = 'Rita', @salary = $3000.00;  
    EXEC dbo.usp_insertemp  
      @empid = 10, @mgrid = 5, @empname = 'Sean', @salary = $3000.00;  
    EXEC dbo.usp_insertemp  
      @empid = 11, @mgrid = 7, @empname = 'Gabriel', @salary = $3000.00;  
    EXEC dbo.usp_insertemp  
      @empid = 12, @mgrid = 9, @empname = 'Emilia', @salary = $2000.00;  
    EXEC dbo.usp_insertemp  
      @empid = 13, @mgrid = 9, @empname = 'Michael', @salary = $2000.00;  
    EXEC dbo.usp_insertemp  
      @empid = 14, @mgrid = 9, @empname = 'Didi', @salary = $1500.00 
    SET NOCOUNT ON;
    USE tempdb;
    GO
    IF OBJECT_ID('dbo.Employees') IS NOT NULL
      DROP TABLE dbo.Employees;
    GO
    CREATE TABLE dbo.Employees
    (
      empid   INT          NOT NULL PRIMARY KEY NONCLUSTERED,
      mgrid   INT          NULL     REFERENCES dbo.Employees,
      empname VARCHAR(25)  NOT NULL,
      salary  MONEY        NOT NULL,
      lvl     INT          NOT NULL,
      path    VARCHAR(900) NOT NULL UNIQUE CLUSTERED
    );
    CREATE UNIQUE INDEX idx_unc_mgrid_empid ON dbo.Employees(mgrid, empid);
    GO
    IF OBJECT_ID('dbo.usp_insertemp') IS NOT NULL
      DROP PROC dbo.usp_insertemp;
    GO
    CREATE PROC dbo.usp_insertemp
      @empid   INT,
      @mgrid   INT,
      @empname VARCHAR(25),
      @salary  MONEY
    AS

    SET NOCOUNT ON;

    -- 如果插入的是一个没有经理的老大
    IF @mgrid IS NULL
      INSERT INTO dbo.Employees(empid, mgrid, empname, salary, lvl, path)
        VALUES(@empid, @mgrid, @empname, @salary,
          0,  CAST(@empid AS VARCHAR(10)));
    --插入有经理的小弟
    ELSE
      INSERT INTO dbo.Employees(empid, mgrid, empname, salary, lvl, path)
        SELECT @empid, @mgrid, @empname, @salary,
          lvl + 1, path +'-'+ CAST(@empid AS VARCHAR(10))
        FROM dbo.Employees
        WHERE empid = @mgrid;
    GO

    EXEC dbo.usp_insertemp
      @empid = 1, @mgrid = NULL, @empname = 'David', @salary = $10000.00;
    EXEC dbo.usp_insertemp
      @empid = 2, @mgrid = 1, @empname = 'Eitan', @salary = $7000.00;
    EXEC dbo.usp_insertemp
      @empid = 3, @mgrid = 1, @empname = 'Ina', @salary = $7500.00;
    EXEC dbo.usp_insertemp
      @empid = 4, @mgrid = 2, @empname = 'Seraph', @salary = $5000.00;
    EXEC dbo.usp_insertemp
      @empid = 5, @mgrid = 2, @empname = 'Jiru', @salary = $5500.00;
    EXEC dbo.usp_insertemp
      @empid = 6, @mgrid = 2, @empname = 'Steve', @salary = $4500.00;
    EXEC dbo.usp_insertemp
      @empid = 7, @mgrid = 3, @empname = 'Aaron', @salary = $5000.00;
    EXEC dbo.usp_insertemp
      @empid = 8, @mgrid = 5, @empname = 'Lilach', @salary = $3500.00;
    EXEC dbo.usp_insertemp
      @empid = 9, @mgrid = 7, @empname = 'Rita', @salary = $3000.00;
    EXEC dbo.usp_insertemp
      @empid = 10, @mgrid = 5, @empname = 'Sean', @salary = $3000.00;
    EXEC dbo.usp_insertemp
      @empid = 11, @mgrid = 7, @empname = 'Gabriel', @salary = $3000.00;
    EXEC dbo.usp_insertemp
      @empid = 12, @mgrid = 9, @empname = 'Emilia', @salary = $2000.00;
    EXEC dbo.usp_insertemp
      @empid = 13, @mgrid = 9, @empname = 'Michael', @salary = $2000.00;
    EXEC dbo.usp_insertemp
      @empid = 14, @mgrid = 9, @empname = 'Didi', @salary = $1500.00
     ;
    ----检测
    SELECT empid, mgrid, empname, salary, lvl, path
    FROM dbo.Employees
    ORDER BY path;
    view plaincopy to clipboardprint?
    /* 
    empid       mgrid       empname                   salary                lvl         path 
    ----------- ----------- ------------------------- --------------------- ----------- --------- 
    1           NULL        David                     10000.00              0           1 
    2           1           Eitan                     7000.00               1           1-2 
    4           2           Seraph                    5000.00               2           1-2-4 
    5           2           Jiru                      5500.00               2           1-2-5 
    10          5           Sean                      3000.00               3           1-2-5-10 
    8           5           Lilach                    3500.00               3           1-2-5-8 
    6           2           Steve                     4500.00               2           1-2-6 
    3           1           Ina                       7500.00               1           1-3 
    7           3           Aaron                     5000.00               2           1-3-7 
    11          7           Gabriel                   3000.00               3           1-3-7-11 
    9           7           Rita                      3000.00               3           1-3-7-9 
    12          9           Emilia                    2000.00               4           1-3-7-9-12 
    13          9           Michael                   2000.00               4           1-3-7-9-13 
    14          9           Didi                      1500.00               4           1-3-7-9-14 
     
    */ 
     
      
    /*
    empid       mgrid       empname                   salary                lvl         path
    ----------- ----------- ------------------------- --------------------- ----------- ---------
    1           NULL        David                     10000.00              0           1
    2           1           Eitan                     7000.00               1           1-2
    4           2           Seraph                    5000.00               2           1-2-4
    5           2           Jiru                      5500.00               2           1-2-5
    10          5           Sean                      3000.00               3           1-2-5-10
    8           5           Lilach                    3500.00               3           1-2-5-8
    6           2           Steve                     4500.00               2           1-2-6
    3           1           Ina                       7500.00               1           1-3
    7           3           Aaron                     5000.00               2           1-3-7
    11          7           Gabriel                   3000.00               3           1-3-7-11
    9           7           Rita                      3000.00               3           1-3-7-9
    12          9           Emilia                    2000.00               4           1-3-7-9-12
    13          9           Michael                   2000.00               4           1-3-7-9-13
    14          9           Didi                      1500.00               4           1-3-7-9-14

    */

     
     

    2.移动子树
    比如说某个部门来了个新老大,原来部门老大和手下的人都要跟着他.这个时候表里的路径和级别都要更新
    Select Empid, Replicate(' | ', Lvl) + Empname As Empname, Lvl, Path
    From Dbo.Employees
    Order By Path;

    --这个是移动之前的层次分布

    view plaincopy to clipboardprint?
    /* 
    empid       empname             lvl             path  
     
    ----------- ----------------- ----------- ------------ 
    1           David                   0           1                      
    2            | Eitan                1           1-2 
    4            |  | Seraph            2           1-2-4                      
    5            |  | Jiru              2           1-2-5            
    10           |  | | Sean            3           1-2-5-10       
    6            |  | Steve             2           1-2-6                 
    3            | Ina                  1           1-3              
    7            |  | Aaron             2           1-3-7                    
    11           |  |  | Gabriel        3           1-3-7-11          
    9            |  |  | Rita           3           1-3-7-9           
    13           |  |  |  | Michael     4           1-3-7-9-13      
    14           |  |  |  | Didi        4           1-3-7-9-14        
    */ 
    /*
    empid       empname             lvl             path

    ----------- ----------------- ----------- ------------
    1           David                   0           1                    
    2            | Eitan                1           1-2
    4            |  | Seraph            2           1-2-4                    
    5            |  | Jiru              2           1-2-5          
    10           |  | | Sean            3           1-2-5-10     
    6            |  | Steve             2           1-2-6               
    3            | Ina                  1           1-3            
    7            |  | Aaron             2           1-3-7                  
    11           |  |  | Gabriel        3           1-3-7-11        
    9            |  |  | Rita           3           1-3-7-9         
    13           |  |  |  | Michael     4           1-3-7-9-13    
    14           |  |  |  | Didi        4           1-3-7-9-14      
    */
     

    ==接下来我们移动
    view plaincopy to clipboardprint?
    IF OBJECT_ID('dbo.usp_movesubtree') IS NOT NULL  
      DROP PROC dbo.usp_movesubtree;  
    GO  
    CREATE PROC dbo.usp_movesubtree  
      @root  INT,--旧经理  
      @mgrid INT--新经理  
    AS  
     
    SET NOCOUNT ON;  
     
    BEGIN TRAN;  
     
      UPDATE E  
        SET lvl  = E.lvl + NM.lvl - OM.lvl,-- 级别=当前的级别+(新经理级别-原经理级别)  
            path = STUFF(E.path, 1, LEN(OM.path), NM.path)  
             -- 路径=自己的路径移除原来经理那部分再加上新的经理的那部分  
             --这里的 OM.path 是被替换经理的经理的路径 比如旧经理是1-3-7 那么OM.PATH 就是1-3   
             --NM.path 是新经理的路径了 比如要换新经理的EMPID是10 所以NM.path  就是 1-2-5-10  
             --所以如果本来旧经理一个手下比如说是1-3-7-10 现在整个替换过来就是1-2-5-10-7-10  
      FROM dbo.Employees AS E          -- E = 员工  
        JOIN dbo.Employees AS R        -- R = 根  
          ON R.empid = @root  
          AND E.path LIKE R.path + '%' 
        JOIN dbo.Employees AS OM       -- OM = 旧经理  
          ON OM.empid = R.mgrid  
        JOIN dbo.Employees AS NM       -- NM = 新经理  
          ON NM.empid = @mgrid;  
     
      -- 更新旧的经理的经理为新来的经理  
      UPDATE dbo.Employees SET mgrid = @mgrid WHERE empid = @root;  
        
    COMMIT TRAN;  
    GO  
     
     
    BEGIN TRAN;  
     
      EXEC dbo.usp_movesubtree  
      @root  = 7,  
      @mgrid = 10;  
     
      -- After moving subtree  
      SELECT empid, REPLICATE(' | ', lvl) + empname AS empname, lvl, path  
      FROM dbo.Employees  
      ORDER BY path;  
     
    ROLLBACK TRAN;  
    IF OBJECT_ID('dbo.usp_movesubtree') IS NOT NULL
      DROP PROC dbo.usp_movesubtree;
    GO
    CREATE PROC dbo.usp_movesubtree
      @root  INT,--旧经理
      @mgrid INT--新经理
    AS

    SET NOCOUNT ON;

    BEGIN TRAN;

      UPDATE E
        SET lvl  = E.lvl + NM.lvl - OM.lvl,-- 级别=当前的级别+(新经理级别-原经理级别)
            path = STUFF(E.path, 1, LEN(OM.path), NM.path)
             -- 路径=自己的路径移除原来经理那部分再加上新的经理的那部分
             --这里的 OM.path 是被替换经理的经理的路径 比如旧经理是1-3-7 那么OM.PATH 就是1-3
             --NM.path 是新经理的路径了 比如要换新经理的EMPID是10 所以NM.path  就是 1-2-5-10
             --所以如果本来旧经理一个手下比如说是1-3-7-10 现在整个替换过来就是1-2-5-10-7-10
      FROM dbo.Employees AS E          -- E = 员工
        JOIN dbo.Employees AS R        -- R = 根
          ON R.empid = @root
          AND E.path LIKE R.path + '%'
        JOIN dbo.Employees AS OM       -- OM = 旧经理
          ON OM.empid = R.mgrid
        JOIN dbo.Employees AS NM       -- NM = 新经理
          ON NM.empid = @mgrid;

      -- 更新旧的经理的经理为新来的经理
      UPDATE dbo.Employees SET mgrid = @mgrid WHERE empid = @root;
     
    COMMIT TRAN;
    GO


    BEGIN TRAN;

      EXEC dbo.usp_movesubtree
      @root  = 7,
      @mgrid = 10;

      -- After moving subtree
      SELECT empid, REPLICATE(' | ', lvl) + empname AS empname, lvl, path
      FROM dbo.Employees
      ORDER BY path;

    ROLLBACK TRAN;

     

    --移动后结果

    view plaincopy to clipboardprint?
    /* 
    empid       empname                            lvl         path                   
     
    ----------- ------------------------------ ----------- ---------------------- 
    1           David                              0           1                       
    2            | Eitan                           1           1-2                          
    4            |  | Seraph                       2           1-2-4              
    5            |  | Jiru                         2           1-2-5              
    10           |  |  | Sean                      3           1-2-5-10          
    7            |  |  |  | Aaron                  4           1-2-5-10-7        
    11           |  |  |  |  | Gabriel             5           1-2-5-10-7-11    
    9            |  |  |  |  | Rita                5           1-2-5-10-7-9            
    12           |  |  |  |  |  | Emilia           6           1-2-5-10-7-9-12     
    13           |  |  |  |  |  | Michael          6           1-2-5-10-7-9-13     
    14           |  |  |  |  |  | Didi             6           1-2-5-10-7-9-14      
    8            |  |  | Lilach                    3           1-2-5-8            
    6            |  | Steve                        2           1-2-6   
    3            | Ina                             1           1-3      
     
                                                                
    */ 
    /*
    empid       empname                            lvl         path                 

    ----------- ------------------------------ ----------- ----------------------
    1           David                              0           1                     
    2            | Eitan                           1           1-2                        
    4            |  | Seraph                       2           1-2-4            
    5            |  | Jiru                         2           1-2-5            
    10           |  |  | Sean                      3           1-2-5-10        
    7            |  |  |  | Aaron                  4           1-2-5-10-7      
    11           |  |  |  |  | Gabriel             5           1-2-5-10-7-11  
    9            |  |  |  |  | Rita                5           1-2-5-10-7-9          
    12           |  |  |  |  |  | Emilia           6           1-2-5-10-7-9-12   
    13           |  |  |  |  |  | Michael          6           1-2-5-10-7-9-13   
    14           |  |  |  |  |  | Didi             6           1-2-5-10-7-9-14    
    8            |  |  | Lilach                    3           1-2-5-8          
    6            |  | Steve                        2           1-2-6 
    3            | Ina                             1           1-3    

                                                              
    */
     


    --这个是移动之后 大家注意观察7 和 10 两位同志

    3.移除子树
    就是把某个部门从公司取消掉
    --首先查看公司部门当前分布
    view plaincopy to clipboardprint?
    SELECT empid, REPLICATE(' | ', lvl) + empname AS empname, lvl, path  
    FROM dbo.Employees  
    ORDER BY path; 
    SELECT empid, REPLICATE(' | ', lvl) + empname AS empname, lvl, path
    FROM dbo.Employees
    ORDER BY path;

    --查询结果
    view plaincopy to clipboardprint?
    /* 
    empid       empname             lvl         path         
     
    ----------- -------------   -------------  ----------- 
    1           David                0           1           
    2            | Eitan             1           1-2       
    4            |  | Seraph         2           1-2-4         
    5            |  | Jiru           2           1-2-5         
    8            |  |  | Lilach      3           1-2-5-8     
    6            |  | Steve          2           1-2-6          
    3            | Ina               1           1-3                   
    7            |  | Aaron          2           1-3-7       
    11           |  |  | Gabriel     3           1-3-7-11   
    9            |  |  | Rita        3           1-3-7-9              
    12           |  |  |  | Emilia   4           1-3-7-9-12    
    13           |  |  |  | Michael  4           1-3-7-9-13  
    14           |  |  |  | Didi     4           1-3-7-9-14     
    */ 
    /*
    empid       empname             lvl         path       

    ----------- -------------   -------------  -----------
    1           David                0           1         
    2            | Eitan             1           1-2     
    4            |  | Seraph         2           1-2-4       
    5            |  | Jiru           2           1-2-5       
    8            |  |  | Lilach      3           1-2-5-8   
    6            |  | Steve          2           1-2-6        
    3            | Ina               1           1-3                 
    7            |  | Aaron          2           1-3-7     
    11           |  |  | Gabriel     3           1-3-7-11 
    9            |  |  | Rita        3           1-3-7-9            
    12           |  |  |  | Emilia   4           1-3-7-9-12  
    13           |  |  |  | Michael  4           1-3-7-9-13
    14           |  |  |  | Didi     4           1-3-7-9-14   
    */

     
    --接着我们来开始一个部门 比如移除Aaron手下的人

     

    view plaincopy to clipboardprint?
    BEGIN TRAN;  
     
      DELETE FROM dbo.Employees  
      WHERE path LIKE  
        (SELECT M.path + '%' 
         FROM dbo.Employees as M  
         WHERE M.empid = 7);  
     
      --删除之后显示  
      SELECT empid, REPLICATE(' | ', lvl) + empname AS empname, lvl, path  
      FROM dbo.Employees  
      ORDER BY path;  
     
    ROLLBACK TRAN; 
    BEGIN TRAN;

      DELETE FROM dbo.Employees
      WHERE path LIKE
        (SELECT M.path + '%'
         FROM dbo.Employees as M
         WHERE M.empid = 7);

      --删除之后显示
      SELECT empid, REPLICATE(' | ', lvl) + empname AS empname, lvl, path
      FROM dbo.Employees
      ORDER BY path;

    ROLLBACK TRAN;

     

    --查询结果

    view plaincopy to clipboardprint?
    /* 
    empid       empname               lvl         path                    
     
    ----------- ------------------ ----------- ------------ 
    1           David                 0           1                        
    2            | Eitan              1           1-2                      
    4            |  | Seraph          2           1-2-4       
    5            |  | Jiru            2           1-2-5       
    10           |  |  | Sean         3           1-2-5-10    
    8            |  |  | Lilach       3           1-2-5-8     
    6            |  | Steve           2           1-2-6   
    3            | Ina                1           1-3 
    */ 
    /*
    empid       empname               lvl         path                  

    ----------- ------------------ ----------- ------------
    1           David                 0           1                      
    2            | Eitan              1           1-2                    
    4            |  | Seraph          2           1-2-4     
    5            |  | Jiru            2           1-2-5     
    10           |  |  | Sean         3           1-2-5-10  
    8            |  |  | Lilach       3           1-2-5-8   
    6            |  | Steve           2           1-2-6 
    3            | Ina                1           1-3
    */
     

    4.查询

     

    这里的查询可就轻松多啦 ~因为路径都有啦~
    --查询EMPID为3的手下一批人

     

    view plaincopy to clipboardprint?
    SELECT REPLICATE(' | ', E.lvl - M.lvl) + E.empname  
    FROM dbo.Employees AS E  
      JOIN dbo.Employees AS M  
        ON M.empid = 3 -- root  
        AND E.path LIKE M.path + '%' 
       --and  E.path LIKE M.path + '_%'--这里那个3号就没了  
       --and  E.lvl - M.lvl <= 2 --限制级数  
       --WHERE NOT EXISTS        --自己本身不是经理的,返回的都是员工  
       (SELECT *  
         FROM dbo.Employees AS E2  
         WHERE E2.mgrid = E.empid);  
    ORDER BY E.path; 
    SELECT REPLICATE(' | ', E.lvl - M.lvl) + E.empname
    FROM dbo.Employees AS E
      JOIN dbo.Employees AS M
        ON M.empid = 3 -- root
        AND E.path LIKE M.path + '%'
       --and  E.path LIKE M.path + '_%'--这里那个3号就没了
       --and  E.lvl - M.lvl <= 2 --限制级数
       --WHERE NOT EXISTS        --自己本身不是经理的,返回的都是员工
       (SELECT *
         FROM dbo.Employees AS E2
         WHERE E2.mgrid = E.empid);
    ORDER BY E.path;

    --查询结果
    view plaincopy to clipboardprint?
    /* 
    ------------------ 
    Ina 
     | Aaron 
     |  | Gabriel 
     |  | Rita 
     |  |  | Emilia 
     |  |  | Michael 
     |  |  | Didi 
     
    */ 
    /*
    ------------------
    Ina
     | Aaron
     |  | Gabriel
     |  | Rita
     |  |  | Emilia
     |  |  | Michael
     |  |  | Didi

    */

    b.嵌套集合
    是书的作者认为用于树建模最完美最高明的解决方案.
    惭愧..太难..准备翻第二次书的时候再研究...

     

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/feixianxxx/archive/2009/11/01/4753783.aspx

    展开全文
  • 层次化寄存器是一种相当常见的体系结构,但是关于其验证技术的文档似乎仍然缺乏。本文将描述“层次寄存器”的含义,并实现层次寄存器创建和集成UVM寄存器模型。然后,验证工程师可以创建UVM序列并对这些寄存器进行.....
    fd70b326c3e609c242174427d602d010.png1、介绍

    UVM的寄存器模型是验证各种寄存器设计的强大工具。利用寄存器模型的基本特点,可以验证简单的寄存器设计,更复杂的寄存器设计通常需要使用寄存器模型的hooks以及callbacks。层次化寄存器是一种相当常见的体系结构,但是关于其验证技术的文档似乎仍然缺乏。

    本文将描述“层次寄存器”的含义,并实现层次寄存器创建和集成UVM寄存器模型。然后,验证工程师可以创建UVM序列并对这些寄存器进行验证。

    2、层次寄存器                                        

    本文将满足以下条件的寄存器定义为层次寄存器:
    • 寄存器在同一设计层次结构中被复制多次

    • 寄存器的每个副本都由相同的地址引用。

    • 在更高层次上启用/禁用单个寄存器副本。

    • 允许任何enable组合。

    2b357f00f166c466a6a32726c82a7c1b.png 1 – 具有层次化寄存器的DUT

    本文将这些寄存器称为‘enabled’寄存器和‘enabler’寄存器。对于多层的层次结构,一些寄存器可能同时满足‘enabled’寄存器和‘enabler’寄存器的条件。‘enabled’寄存器通常也称为‘replicated’寄存器层次化寄存器减少了所需寄存器地址的数量,并允许较低层次的并行访问。

    3、UVM寄存器模型面临的挑战

    层次化寄存器使用“启用”方案。然而,层次化寄存器也带来了很多挑战,这些寄存器存在于同一个地址,并且可以并行访问。本文将进一步详细讨论这些挑战。

    4、UVM寄存器模型解决方案

    本文提出了一种涉及一些先进的UVM寄存器模型技术的解决方案。这里列出了其中的重点,然后进一步详细讨论。
    • 为每个设计寄存器实例在UVM寄存器模型中创建一个唯一的uvm_reg实例

    • 在每个较低层次结构的enabler寄存器中创建一个域

    • 对于设计中复制的寄存器,使用设计的地址范围之外的地址。这避免了具有相同地址的多个uvm_reg实例的问题。

    • 确保sequence item地址大小与寄存器模型地址大小匹配。

    • 确保driverBFM地址大小匹配DUT的地址大小。

    • 扩展uvm_reg_predictor来预测enabled寄存器的多个副本。

    • 使用回调实现enabledenabler寄存器的行为。例如,寄存器的镜像值只有在寄存器被选中时才会更新。

    4.1 创建唯一的uvm_reg实例

    对于设计中每个复制的enabled寄存器,我们的寄存器模型中都有一个对应的唯一实例uvm_reg(实际上是寄存器的uvm_reg扩展)。这样,每个设计寄存器都可以受益于UVM寄存器模型的特性,比如镜像值和peek/poke功能。我们通过创建一个模仿DUT设计的寄存器块层次结构来实现这一点,从而为DUT的每个复制部分或模块提供一个唯一的寄存器块。唯一的寄存器块通常被实现为更高级别寄存器块中的寄存器块数组。

    4.2 创建Enabler寄存器域

    许多DUT设计可能具有enabler寄存器,其中寄存器的每一位都选择(启用)一个复制的较低层次结构。在本例中,我们必须enabler寄存器的每个位创建一个uvm_reg_field。这些单独的域将用于正确预测enabled寄存器,稍后将对此进行讨论。

    4.3 寄存器模型地址

    UVM寄存器模型要求每个寄存器实例都有一个唯一的地址。这是一个挑战,因为每个复制的DUT寄存器使用相同的地址。因此,我们必须为这些寄存器分配与它们的DUT地址不匹配的地址。克服这个问题的一个简单方法是,我们的寄存器模型使用一个大于DUT的地址空间。

    例如,假设我们有一个DUT,它使用16位地址,并且有一组层次化寄存器,这些寄存器被复制了4次。在这种情况下,我们的寄存器模型可以使用18位地址,并且位[17:16]可以用来标识每个唯一的复制寄存器。这样,复制的寄存器地址的16LSBs是相同的,并且匹配DUT使用的地址。我们将看到,当我们预测寄存器值并执行前门操作时,这种类型的寄存器模型寻址方案非常有用。

    4.4 Sequence Item地址大小

    与许多UVM寄存器模型实现一样,我们的寄存器模型将连接到agent并使用显式预测。因此,我们必须确保adaptorpredictor使用的Sequence Item中的地址足够大,以匹配寄存器模型的地址大小。Sequence Item的地址大小不足以匹配DUT的地址大小。当我们讨论扩展uvm_reg_predictor时,这一点将变得很明显。

    4.5 Driver/BFM地址大小

    如果寄存器模型地址是如上所述分配的,那么它们的大小就不匹配DUT的地址大小。因此,当向DUT显示事务时,driverBFM必须忽略sequence item中地址的MSBs这允许sequence对寄存器模型中的任何寄存器执行前门寄存器操作,尽管它们的地址大小不匹配相应的DUT地址大小。注意,前门操作只会影响所选的DUT寄存器。因此,如果一个序列对一个复制寄存器执行前门操作,那么相应的DUT寄存器可能不会被执行,而/或其他复制寄存器可能被执行。

    如果使用了后门路径,那么序列和分析组件可以使用peekpoke操作分别操作每个寄存器副本。

    4.6 扩展uvm_reg_predictor

    一个对应于复制寄存器的DUT地址的单一前门操作将根据enabler寄存器的当前状态执行01或多个DUT寄存器复制。因此,我们的寄存器模型必须对多个寄存器执行预测,尽管只有一个前门操作和一个地址。我们通过扩展uvm_reg_predictor来实现这一点。

    我们的扩展uvm_reg_predictor在我们的monitorpredictor写入一个与复制寄存器对应的地址的事务时,会发出多个预测调用,每个预测调用针对一个复制寄存器。它通过覆盖基预测器的写任务来实现多次调用super.write,每次用一个新的地址对应一个不同的寄存器副本。正是由于这个原因,sequence item的地址大小必须足够大,以匹配我们的寄存器模型中的地址大小

    4.7 实现Enabled寄存器预测

    必须根据enabled寄存器的状态对enabler寄存器进行适当的预测。我们使用post_predict回调实现enabled寄存器行为。该技术面临一些挑战。第一个挑战是,对于多级层次结构,我们的enabled域可能需要考虑多个enabler。因此,我们将一个enabler域队列传递给回调的构造函数,回调检查post_predict函数中的所有enabler域。第二个挑战涉及前门读取操作,因为DUT寄存器副本中的值可能不同。因此,必须考虑当选择多个寄存器时DUT的读取行为。一种常见的行为是,DUT在读取期间对所有选定的寄存器逐位进行或/与操作。对于这样的行为,我们不应该在前端或读取操作期间更新寄存器的镜像值,因为无法知道哪些寄存器具有哪些值。当然,例外情况是只选择一个enabled寄存器副本。在这种情况下,我们可以安全地更新所选寄存器的镜像值。

    post_predict回调函数除了enabler域外,还需要信息来检查是否只选择了enabled寄存器。它还需要知道与其他寄存器块中其他enabled寄存器相对应的enabler域的状态。因此,我们将一个不对应的enabler域队列传递给回调的构造函数,回调将检查post_predict函数中相应的和非相应的enabler域。

    5 、应用举例

    接下来将根据上一节的讲述举一个简单的例子。这个示例是一个有三个层次结构的DUT,他的三层结构为:高、中、低。每个层次结构级别的每个副本上都存在一个RW调试寄存器Enabler寄存器存在于层次结构的较高级别,以启用层次结构的较低级别。我们的示例设计有4个中等层次结构,其中,每个中等层次结构中有4个低层次结构。高级模块包含一个位于地址0x2的“中级启用”寄存器。“中级启用”寄存器有4位宽,每个位选择(启用)一个中级模块。每个中级模块都包含一个位于地址0x100的“debug”寄存器和一个位于地址0x102的“低级启用”寄存器。每个“低级启用”寄存器有4位宽,每个位选择(启用)中级模块中的一个低级模块。每个低级模块都包含一个位于地址0x1000的“debug”寄存器。具体的设计框图如图2所示。14331b6633a365c8fad8f06ec5cce26d.png2 – 设计框图当主机执行读取操作时,我们的示例设计对所有选定寄存器(设置了相应的使能位的寄存器)实现按位或。使用16位地址(0x0- 0xFFFF)。这在分配寄存器模型地址时非常重要。

    55679ffe8cfbf2a1895f0f1a502af7d1.png

    5-1 - 示例设计寄存器

    注意,必须为LOW_LVL_DBG寄存器实例设置相应的MED_LVL_EN位和LOW_LVL_EN位,以响应读和写。下面几节将演示寄存器模型解决方案的每个步骤

    5.1 创建唯一的uvm_reg实例

    我们用寄存器块的层次结构创建了一个寄存器模型,它模仿DUT中模块的层次结构。

    2b8bf6ca3556cbbdcdcf3b52c9b8c066.png

    5-2 -寄存器模型结构5-2 -寄存器模型结构包含21个寄存器块和26个寄存器如果我们正确地实现了表5-2,那么low_lvl_dbg_reg实例的地址将如表5-3所示。

    fa3fd9f7135602ceceae23b8c7a371c5.png

    5-3 - low_lvl_dbg_reg地址

    5.2 创建Enabler寄存器域

    我们为enabler寄存器的每一位创建uvm_reg_field。每个域都是根据位所启用的DUT模块来命名的。med_lvl_en_reg的代码如下:

    0d06dc08ec37e41f123f925fc16d4ad5.png

    5.3 寄存器模型地址

    所需的寄存器地址如表5-2和表5-3所示。注意,寄存器模型需要22位地址空间,这比DUT16位地址空间要大。我们可以选择不同的块复制偏移量来减少所需的地址空间位的数量。例如,low_lvl_reg_block的块复制偏移量可以是0x4_0000,但是使用0x10_0000允许我们对位使用十六进制数字[21:20][19:16],以便更容易地确定地址对应的是哪个复制。所选的块复制偏移量也允许我们在将来需要时更容易地增加复制的数量。为寄存器块正确地设置uvm_reg_map实例的地址偏移量,如下所示:

    c9706108229ae74ae194b2b21422a4ee.png

    5.4 Sequence Item地址大小

    我们的寄存器模型设计要求Sequence Item中的地址至少为22位宽

    5.5 driver/BFM地址大小

    我们的DUT使用16位地址空间。因此,我们的driverBFM在向DUT显示事务时必须忽略Sequence Item中地址的6msb对任何一个复制寄存器的读写操作将导致在连接到DUT的接口/BFM上执行相同的操作。例如,写入hi_lvl_reg_block.med_lvl_reg_block[2].low_lvl_reg_block[3]

    low_lvl_dbg_reg将导致接口/BFMDUT发送一个写操作,地址为0x1000(而不是0x32_1000)

    5.6 扩展uvm_reg_predictor

    我们的寄存器预测器检查每个事务,看看它是否对应于一个复制的寄存器。如果是,它将对每个具有适当地址的复制寄存器发出predict调用。我们的预测器的代码如下:

    a529bbc10d1bf20ef8e113b56e20fd09.png

    5.7 实现Enabled寄存器预测

    我们在寄存器模型中为每个enabled寄存器的每个域注册一个post_predict回调。在读取期间,我们的DUT执行一个所有选择的寄存器的位或操作。因此,我们不能准确地更新寄存器的镜像值,除非只选择一个寄存器,以便我们的回调接收前面讨论的两个寄存器域队列。这里显示了回调代码。请注意,回调如何检查域队列是否适合写和读操作。回调包含一个uvm_info消息,当选择多个寄存器执行读操作时,验证工程师可能希望使用该消息。还要注意enabler队列检查是如何为前门操作执行的。因此,enabler域的状态不会影响enabled寄存器的peek和pokef0ccedfef042c11cf759a74cf240d894.png我们创建enabler域队列,并在测试的构建阶段注册回调,如下所示:3e81282ff915ca34877684a0e58eb52a.png

    b68976213792e767b773def97679eccb.png

    6、结论

    本文提出了一种利用UVM寄存器模型对层次寄存器进行建模的解决方案。也许这个解决方案最重要的方面是为DUT中的每个寄存器实例创建一个唯一的UVM寄存器实例,而这两个实体的地址并不相同。而在典型的UVM寄存器实现中,UVM寄存器地址与DUT地址相同。希望这个解决方案为读者提供了一些关于如何使用层次化寄存器对特定DUT进行建模的想法

    原文来自:DVCon2017_USA,点击阅读原文去路科官网下载DVCon2017论文合集,还有更多资料等你来哦!0472d0e169c6c862bca2cf06b16497f3.png

    往期精彩:

    30w+还送股送房?60+IC企业2019薪资全面攀升!UVM RAL模型:用法和应用我们准备做第二期线下培训,依旧认真且严肃如果你突然被裁员了,你的Plan B是什么?[彩虹糖带你入门UVM]理解UVM-1.2到IEEE1800.2的变化,掌握这3点就够65af475dd597af6e4f346cc622b80374.png
    展开全文
  • 一般模型有:员工组织(树,层次结构);料表--BOM(有向);道路系统(无向循环)1.迭代/递归迭代可以迭代的一个节点,也可以迭代一个层次.后者比前者要快很多.实现方法:SQL2000通过UDF(用户自定义函数),SQL2005使用...

    在RDBMS中操作 图 树 层次结构 等特殊的数据结构时,我们通常采用2个主要方法:
    1.基于迭代/递归

    2.具体化描述数据结构的附加信息
    一般模型有:员工组织图(树,层次结构);料表--BOM(有向图);道路系统(无向循环图)


    1.迭代/递归
    迭代可以迭代图的一个节点,也可以迭代一个层次.后者比前者要快很多.
    实现方法:SQL2000通过UDF(用户自定义函数),SQL2005使用CTE

     

    a.下属问题(通俗说,求子节点)
    --这里我使用书上的员工表(表内容如下)


    --SQL2000 udf方法:

     

     

    --SQL2005 CTE

     

     

     

    --查询结果


    ---------------如果需要限制递归的层数------------


    --SQL2000

     

     

    --查询结果


    SELECT empid, lvl
    FROM dbo.fn_subordinates2(2, NULL) AS S;


    PS:这里控制返回的层数 你当然可以用最开始的方法,然后再筛选语句里控制层数
     如SELECT empid, lvl FROM dbo.fn_subordinates1(3) AS S where lvl<3;  但是控制本身的递归只能在UDF里面了
     
     --sql2005方法类似


     

    --还有一种偏方:但是不推荐 虽然结果正确 但是会报错

     

    --查询结果

     
     


    b.祖先(通俗说:求父节点)
    其实思路跟子节点差不多


    --SQL2000


    --查询结果


    SELECT empid, lvl
    FROM dbo.fn_managers(8, 2) AS M;

     

     

    --sql2005

     

    C.层次显示

     

    --SQL2000,思路跟下属问题一模一样 只是多了个PATH

    --这里的显示分2种
    --显示1
    select empid ,pos=REPLICATE('-',lvl)+rtrim(empid)
    FROM dbo.fn_subordinates3(1, NULL) AS S
    ORDER BY PATH


    --还有一种
    SELECT empid,  path
    FROM dbo.fn_subordinates3(1, NULL) AS S
    ORDER BY PATH

    --当然上面的显示方式还很多,自己可以控制 比如不加ORDER 就可以排出不一样的

     

    --SQL2005
    ;

     

    --结果查询

     

     

    D.检测循环中异常
    说白了 就是检查表里有没出现1-2-4-1这种头接尾的圈.这在现实中是不可能的.一个经理部可能是它手下的手下.-- ||
    我们对表做手脚,把老大的经理改成是它的一个员工

     

    --查询结果


    --这样管理员可以轻易找到那个错误的地方.
    改过来:UPDATE dbo.Employees SET mgrid = NULL WHERE empid = 1;

     

     

    2.具体化路径
    这里就是新增加2列,一列是级别 一列是节点路径,这样可以避免每次都去计算.
    2个优点:不需要递归,只需要基于集合 ;查询可以使用到路径索引

     

    a.维护数据


    1.添加不管理员工的员工
    ;
    ----检测
    SELECT empid, mgrid, empname, salary, lvl, path
    FROM dbo.Employees
    ORDER BY path;

     

     

    2.移动子树
    比如说某个部门来了个新老大,原来部门老大和手下的人都要跟着他.这个时候表里的路径和级别都要更新
    Select Empid, Replicate(' | ', Lvl) + Empname As Empname, Lvl, Path
    From Dbo.Employees
    Order By Path;

    --这个是移动之前的层次分布

     

    ==接下来我们移动

    --移动后结果

     


    --这个是移动之后 大家注意观察7 和 10 两位同志

     

    3.移除子树
    就是把某个部门从公司取消掉
    --首先查看公司部门当前分布

     

    --查询结果

    --接着我们来开始一个部门 比如移除Aaron手下的人


     

    --查询结果

     

    4.查询


    这里的查询可就轻松多啦 ~因为路径都有啦~
    --查询EMPID为3的手下一批人


     

    --查询结果

     

    b.嵌套集合
    是书的作者认为用于树建模最完美最高明的解决方案.
    惭愧..太难..准备翻第二次书的时候再研究...

     

    展开全文
  • OSI模型全称“开放式系统互联通信参考模型”,OSI模型的核心是OSI/RM协议,它是由国际标准组织(ISO)提出的,OSI模型的划分是严格明确的,基本结构由下到上划分为:物理层、数据链路层、网络层、传输层、会话层、...
  • 一般模型有:员工组织(树,层次结构);料表--BOM(有向);道路系统(无向循环) 1.迭代/递归 迭代可以迭代的一个节点,也可以迭代一个层次.后者比前者要快很多. 实现方法:SQL2000通过UDF(用户自定义函数),...
  • IDEF0是活动模型的缩写,来源于结构化分析与设计技术的一套标准,这些标准包含多种层次的图形语言,其中IDEFO用来描述对于企业具有重要性的各个过程(活动)。它以图形表示完成一项活动所需要的具体步骤、操作、数据...
  • 软件工程:将系统的、规范的、可度量的工程方法应用于软件开发、运行和维护的全过程及上述方法的研究。1.4.1需求分析 需求分析:是指用户解决问题或达到目标所需的条件或能力 1.4.1.1需求层次分为:业务需求、用户...
  • 结构化分析建模

    千次阅读 2017-02-19 11:56:23
    围绕着这个核心有三个层次的子模型,数据模型、功能模型和行为模型。    数据流服务于两个目的: 指明数据在系统中移动时如何被变换; 描述对数据流进行变换的功能(和子功能)。   数据模型
  • 模型利用超立方拓扑结构对MapReduce的映射操作进行改进,通过特定算法将八个结构化的数据中心链接到一个对等的云环境结构中,并使用奇偶直方组合采样方式的均衡划分方法,实现在用户请求下的节点工作负荷指数...
  • 一、协议当谈到 Internet 时,我们总能听到的一个词汇就是协议...协议的另一个好处是,通信不只是用于两个端系统,中间系统只需要一些层次而不是所有的层次。如果不使用协议分层,形成的中间系统就不得不像端系统一...
  • 结构化软件设计的具体步骤 1.从需求分析阶段的数据流出发,指定几个方案,从中选择合理的方案。 2.采用某种设计方法,将一个复杂的系统按功能划分成模块的层次结构 3。确定每个模块的功能及模块间的调用关系,建立...
  • 一、卷积神经网络分为以下层次: 一般的层次为:输入层-&gt;卷积层-&gt;ReLU激励层-&gt;池化层-&gt;全连接层 各层参数的个数: ...图像里只用去均值---中心--加减某值--目的...
  • 选择预训练模型将深度学习应用于小型图像数据集...预训练的模型学到的特征的空间层次结构可以有效地作为视觉世界的通用模型较低层学到的结构都是一些点线等低层次的特征,这里使用的预训练的模型的数据是 ImageNet ...
  • 在原模型层,UML元模型 又被分解为三个子逻辑包:基础包(核心、扩展机制和数据模型)、行为元素包(描述模型动态行为的语言上层结构,支持不同的行为)、模型管理包(定义了对模型元素进行分组和管理的语义)。...
  • 常用的数据模型

    2020-07-20 19:00:57
    在格式化模型中数据结构的单位是基本层次联系。所谓的基本层次联系是指两个记录以及它们之间的一对多(包括一对一)的联系。 中Rj位于联系Lij的始点,称为双亲结点。Rj位于联系Lij的终点,称为子女节点。 ...
  • 一、单项选择题1.要保证数据库的数据独立性,需要修改的是( )A.三层模式之间的两种映射 B.模式与内模式C.模式与外模式 D.三层模式2.学生社团可以接纳多名学生参加,但每个学生...层次模型 C.网状模型 D. E-R模型4...
  • 分别对应什么结构层次模型、网状模型和关系模型是三种重要的数据模型。这三种模型是按其数据结构而命名的。...关系模型为非格式结构,用单一的二维表的结构表示实体及实体之间的联系。满足一定条件的...
  • 自动机由状态和变迁两部分组成,其翻译涉及到将状态和变迁上所对应的内容翻译到可以描述模型的代码上。自动机提供了整个所需执行逻辑的框架,框架有变迁、状态、组件组成。 翻译可以看成是由两部分构成,对框架内每...
  • OSI模型 ...OSI参考模型只是描述了一些概念,定义了网络通信协议的层次结构层次之间的相互关系以及各层可能包括的任务。 OSI模型一共分为7个层次,如下所示,从上到下依次为:应用层(第7层)、表示
  • 从原理上说可以使用张量构建计算来定义神经网络,并通过自动微分机制训练模型。但为简洁起见,一般推荐使用TensorFlow的高层次keras接口来实现神经网络网模型。使用TensorFlow实现神经网络模型的一般流程包括:1,...
  • matlab-层次分析法

    2019-09-28 23:17:11
    层次分析法(AHP)是把问题条理化、层次化,构造出一个有层次的结构模型的方法。 比如要选择旅游地,有3个选择方案,苏杭、北戴河和桂林。选择过程需要考虑多个因素,比如景色、费用、居住、饮食和旅途。 1.分为...
  • 场景的图像具有不同的对象和...利用这一丰富的信息和一个先进的深度学习框架,并提出了一个通用的结构化模型,利用不同的标签关系来提高图像分类性能。我们的方法使用了堆叠标签预测网络,捕获了层间和层内标签语义。
  • 网络中的OSI模型

    2018-12-22 17:41:08
    简单来说就是,当时不同公司用的网络标准不同,总是会有兼容性问题发生,然后这个组织就定义了一套层次化结构的网络模型,希望大家都按照这个标准来。 OSI模型的7层模型 图片感觉太高度概括了,我来举个例子:...
  • zookeeper数据模型

    千次阅读 2015-12-01 21:28:05
    这样就构成了类似文件系统的层次化命名空间。其实就是树形结构。 下是Zookeeper节点的数据模型: Znode从持久化的角度来说,可以分类两类: 持久化节点(PERSISTENT Node):创建新增删除等操作会更新到事务....

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 453
精华内容 181
关键字:

层次化模型结构图