查找每个节点的层次结构

Find Hierarchy for each Node

我正在尝试重建当前使用“RBAR”方法来映射我组织的报告层次结构的存储过程。当组织规模较小时,这种方法很管用,但随着组织规模的扩大,这种方法的规模就完全不适用了。

我想做的是使用递归 CTE 来帮助加快进程。我尝试的第一步奏效了;映射层次结构中与 first/top 节点相关的每个位置。

我的数据看起来与此类似:

POSITION_NBR | REPORTS_TO |
     001           001
     002           001
     003           001
     004           002
     005           003
     006           003
     007           004

我目前的做法return这个:

REPORTS_TO | POSITION_NBR | EMPLEVEL
    001           001          0
    001           002          1
    001           003          1
    002           004          2
    003           005          2
    003           006          2
    004           007          3

这是我的 SQL:

WITH POSN_HIERARCHY AS 
    (SELECT POS.REPORTS_TO
            ,POS.POSITION_NBR
            ,0 AS EMPLEVEL
    FROM dbo.POSITION_BASE POS
    WHERE POS.POSITION_NBR = POS.REPORTS_TO

    UNION ALL

    SELECT POS.REPORTS_TO
            ,POS.POSITION_NBR
            ,EMP.EMPLEVEL + 1
    FROM dbo.POSITION_BASE POS
    INNER JOIN POSN_HIERARCHY EMP
        ON EMP.POSITION_NBR = POS.REPORTS_TO
    WHERE POS.POSITION_NBR <> POS.REPORTS_TO)

SELECT * FROM POSN_HIERARCHY

我正在苦苦挣扎的是一种方法,不仅可以找到与第一个节点相关的层次结构,还可以找到主层次结构中的每个 层次结构。例如,我现在的 SQL 会在主要组织的结构中找到我的级别,但我也希望能够在我的经理的层次结构中看到我的级别,以及他的经理的层次结构等。

所以基本上我正在尝试 return 组织中每个经理的层次结构。

我理想的输出是这样的:

REPORTS_TO | POSITION_NBR | EMPLEVEL
    001           001          0  
    001           002          1
    001           003          1
    001           004          2
    001           005          2
    001           006          2
    001           007          3
    002           004          1
    002           007          2
    003           005          1
    003           006          1
    004           007          1

所以输出显示了每个人相对于它上面的每个父节点的级别。 (007是001的3级,002的2级,004的1级。)

我已经尝试修改锚查询,以便它 return 所有经理,但这没有用。我尝试查看 CTE 中的多个递归,但我也无法使其正常工作。有人可以为我指明正确的方向吗?

CREATE TABLE #POSITION_BASE(POSITION_NBR VARCHAR(20), REPORTS_TO VARCHAR(20))

INSERT INTO #POSITION_BASE
SELECT '001','001'
UNION ALL
SELECT '002','001' 
UNION ALL
SELECT '003','001' 
UNION ALL
SELECT '004','002' 
UNION ALL
SELECT '005','003' 
UNION ALL
SELECT '006','003' 
UNION ALL
SELECT '007','004' 

我已经在查询里面写了逻辑

;WITH POSN_HIERARCHY AS 
(
    -- This is your first query in question. There is no changes here.
    SELECT POS.REPORTS_TO ,POS.POSITION_NBR ,0 AS EMPLEVEL
    FROM #POSITION_BASE POS    
    WHERE POS.POSITION_NBR = POS.REPORTS_TO

    UNION ALL

    SELECT POS.REPORTS_TO ,POS.POSITION_NBR ,EMP.EMPLEVEL + 1
    FROM #POSITION_BASE POS
    INNER JOIN POSN_HIERARCHY EMP
        ON EMP.POSITION_NBR = POS.REPORTS_TO
    WHERE POS.POSITION_NBR <> POS.REPORTS_TO
 )
 ,CTE2 AS
 (
     -- There will be no change to top-level parent and the child just below it.
     -- We select the children whose primary level is greater than one
     SELECT POSITION_NBR,REPORTS_TO,0 EMP
     FROM POSN_HIERARCHY     
     WHERE EMPLEVEL > 1  

     UNION ALL

    -- Finds all the parents for the children whose primary level is greater than one
    SELECT CTE.POSITION_NBR ,C.REPORTS_TO ,EMP + 1
    FROM CTE2 CTE
    INNER JOIN POSN_HIERARCHY C  ON C.POSITION_NBR = CTE.REPORTS_TO
    WHERE C.POSITION_NBR <> C.REPORTS_TO 
 )
 -- We select the top-level parent and the child just below it
 SELECT REPORTS_TO REPORTS_TO,POSITION_NBR,EMPLEVEL
 FROM POSN_HIERARCHY
 WHERE EMPLEVEL < 2

 UNION

 -- We select the children whose primary level is greater than one and its parents
 -- and increment the number by one to meet our requirement
 SELECT REPORTS_TO ,POSITION_NBR,EMP + 1 EMP
 FROM CTE2 
 OPTION(MAXRECURSION 0)

由于SQL FIDDLE有一些内部错误,您可以看到下面的图像结果。

结果