在SQL Server中的特定行上应用递归函数

时间:2014-05-13 20:02:55

标签: sql-server stored-procedures recursion

我试图将这两个想法结合起来

  1. 递归函数 - http://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx

  2. SQL Call Stored Procedure for each Row without using a cursor

  3. 实际上我有两个人分别工作

    我可以获得一个递归函数来工作 我可以让一个存储过程在一行上工作
    但我很难搞清楚 如何让我的递归存储过程在选定的行上工作

    我也在引用这篇文章:
    sql recursive function - to find managers

    所以,如果我有一个特定的行

    id    mngr_id    person_id
    --    -------    ---------
    12       1777          923
    

    我想算一下有mngr_id = null的CEO的多少级别 (如上例中的一个例子)

    这个问题的第二部分:
    如果我想在随机数量的特定行上执行此操作 这会是有效的方法吗?

    [编辑后澄清]
    此代码(根据我上面的示例数据调整)
    来自上面的例子1是优秀的并且运作良好

    GO
    WITH levels (mngr_id, person_id, id, Level)
    AS
    (
    -- Anchor member definition
        SELECT e.mngr_id, e.person_id, e.id, 0 AS Level
        FROM MyEmployees AS e
        WHERE mngr_id IS NULL
        UNION ALL
    -- Recursive member definition
        SELECT e.mngr_id, e.person_id, e.id, Level + 1
        FROM MyEmployees AS e
        INNER JOIN levels AS d
            ON e.mngr_id= d.person_id
    )
    -- Statement that executes the CTE
    SELECT mngr_id, person_id, id, Level
    FROM levels 
    where id=@whatever_random_id_i_choose  -- <---- pseudocode
    GO
    

    请注意:
    为什么我的帖子是cuase我的伪代码不起作用的原因
    当person_id不唯一时中断

    谢谢大家的意见

1 个答案:

答案 0 :(得分:1)

您最好的选择是使用递归公用表表达式。这样您也可以在视图中使用它。

WITH ORG_STRUCTURE
AS (
    SELECT 
         id
        ,mngr_id
        ,person_id
        ,0 AS c_level
    FROM occupancies
    WHERE person_id = @target_user_id


    UNION ALL

    SELECT
          id
        ,mngr_id
        ,person_id
        ,ORG.c_level  + 1 AS c_level
    FROM ORG_STRUCTURE ORG
        INNER JOIN occupancies MAN
            ON ORG.manager_id = MAN.person_id

    -- prevents recursion errors if you have an incomplete org structure
    WHERE c_level < 100
)

SELECT
     id
    ,mngr_id
    ,person_id
    ,MAX(c_level)
FROM ORG_STRUCTURE
WHERE mngr_id IS NULL
GROUP BY id
    ,mngr_id
    ,person_id

递归CTX只能深入100层,所以如果你有一个不完整的org结构,你需要在第二个查询中添加一个throttle where子句(参见注释)。

如果您有一个格式良好的组织结构,则可能不需要group by和MAX()。你可以把它放在一个存储的proc @target_user_id中。如果您只希望返回与CEO的距离,您可以将选择从CTE限制为:

SELECT
    ,MAX(c_level)
FROM ORG_STRUCTURE
WHERE mngr_id IS NULL