sql递归cte在视图中工作不正常

时间:2016-06-17 11:18:51

标签: sql sql-server recursion view common-table-expression

我做了一个CTE查询,它可以在存储过程中正常工作,当我在查询编辑器中执行时(使用where语句)

但是当我尝试创建与View相同时(没有where语句)。 并使用where语句执行此操作,我得到的数据不是递归的。 我没有看到错误。

这是SP中的查询和查询编辑器,它工作正常。 (SP中的Guid作为参数)

WITH recursiveTable(ParentApplicationRoleId, ChildApplicationRoleId)
AS
(
    SELECT ParentApplicationRoleId, ChildApplicationRoleId
        FROM ApplicationRoleParentChild
        WHERE ParentApplicationRoleId = '69BCC94B-2884-4270-B39E-A09669C1D658'
    UNION ALL
    SELECT ApplicationRoleParentChild.ParentApplicationRoleId, ApplicationRoleParentChild.ChildApplicationRoleId
        FROM ApplicationRoleParentChild
        INNER JOIN recursiveTable ON ApplicationRoleParentChild.ParentApplicationRoleId = recursiveTable.ChildApplicationRoleId   
)
/* Get all Childelements (from recursive Table) and add the ParentRoleId to this List */
SELECT ApplicationRole.Name AS RoleName
    FROM recursiveTable
    INNER JOIN ApplicationRole ON ApplicationRole.ApplicationRoleId = recursiveTable.ChildApplicationRoleId 
    UNION
    SELECT Name AS RoleName FROM ApplicationRole WHERE ApplicationRoleId = '69BCC94B-2884-4270-B39E-A09669C1D658'
OPTION(MAXRECURSION 32767)

结果我得到Result Image

View需要所有ApplicationRoles(包含所有Childroles)并且未经过滤,因为我在调用View时会使用过滤器。

如何在没有where语句的情况下更改它的CTE?

我以此为例。但它只返回'管理员'的直接成员 我也从Childs中搜索Child。

WITH recursiveTable(ParentApplicationRoleId, ChildApplicationRoleId)
AS
(
    SELECT ParentApplicationRoleId, ChildApplicationRoleId
        FROM ApplicationRoleParentChild
    UNION ALL
    SELECT ApplicationRoleParentChild.ParentApplicationRoleId, ApplicationRoleParentChild.ChildApplicationRoleId
        FROM ApplicationRoleParentChild
        INNER JOIN recursiveTable ON ApplicationRoleParentChild.ParentApplicationRoleId = recursiveTable.ChildApplicationRoleId   
)
/* Get all Childelements (from recursive Table) and add the ParentRoleId to this List */
    SELECT ApplicationRole.Name AS ChildRoleName, Parent.Name AS ParentRoleName
    FROM recursiveTable
    INNER JOIN ApplicationRole ON ApplicationRole.ApplicationRoleId = recursiveTable.ChildApplicationRoleId 
    INNER JOIN ApplicationRole as Parent ON Parent.ApplicationRoleId = recursiveTable.ParentApplicationRoleId 

/*The Query-Filter when i call the View: Like SELECT * FROM View WHERE Parent.Name = 'Administrator'
    Expected Returns: Role1-10, Departement1-3 and Administrator
    Current Returns: Only direct Childs (Role2,7,8, Departement1,3)

    Departement2 is Child of Departement1
    And some other Roles are in one of the Departements or roles
*/

表: ApplicationRole(所有角色) ApplicationRoleParentChild(所有父子关系)(使用FK父级和FK子角色)

我希望有人可以帮助我。

由于

1 个答案:

答案 0 :(得分:0)

yor where子句过滤所有记录。更深层的记录没有直接的父管理员。 要按其过滤,您可以将顶级记录名称存储为cte

中的列
WITH recursiveTable(ParentApplicationRoleId, ChildApplicationRoleId, TopLevelName)
AS
(
    SELECT ParentApplicationRoleId, ChildApplicationRoleId, Name
        FROM ApplicationRoleParentChild
    UNION ALL
    SELECT ApplicationRoleParentChild.ParentApplicationRoleId, ApplicationRoleParentChild.ChildApplicationRoleId
        , recursiveTable.TopLevelName
        FROM ApplicationRoleParentChild
        INNER JOIN recursiveTable ON ApplicationRoleParentChild.ParentApplicationRoleId = recursiveTable.ChildApplicationRoleId   
)

或者你甚至可以建立孩子的完整路径

   WITH recursiveTable(ParentApplicationRoleId, ChildApplicationRoleId, TopLevelName)
    AS
    (
        SELECT ParentApplicationRoleId, ChildApplicationRoleId, cast(Name as varchar(1000))
            FROM ApplicationRoleParentChild

        UNION ALL
        SELECT ApplicationRoleParentChild.ParentApplicationRoleId, ApplicationRoleParentChild.ChildApplicationRoleId
            , left(recursiveTable.TopLevelName + '/' + name, 1000)
            FROM ApplicationRoleParentChild
            INNER JOIN recursiveTable ON ApplicationRoleParentChild.ParentApplicationRoleId = recursiveTable.ChildApplicationRoleId   
    )

然后过滤where Parent.TopLevelName like '%Administrator%'

<强>更新 如通知 Ivan Starostin 在他的评论中 如果你不打算将每个记录的所有层次结构作为最高级别。 您必须为cte中的第一个选择添加where子句以定义topLevel节点。 类似ParentApplicationRoleId is NULLParentApplicationRoleId = ''

的内容