递归查询(CTE)以查找存档权限

时间:2014-05-18 12:47:15

标签: sql sql-server common-table-expression recursive-query

我有两张桌子:

CREATE TABLE [Archives](
[Id] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
[ParentArchiveId] [int] NULL


CREATE TABLE [ArchivePermissions](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [ArchiveId] [int] NOT NULL,
    [UserId] [int] NULL,
    [PermissionId] [int] NULL

我需要找到存档的权限。

如果存档没有我必须访问的用户的权限,则存档到父存档直到最高存档。

我正在尝试用CTE做这件事:

            ;WITH RESULT (ParentArchiveId,ArchiveId, PermissionId, UserId, Level)
        AS
        (
             --anchor
             SELECT E.ParentArchiveId,E.[Id], A.PermissionId, UserId ,0 AS Level
             FROM Archives AS E  
             LEFT JOIN ArchivePermissions AS A ON e.Id = A.ArchiveId
             WHERE E.Id = @ArchiveId
             AND A.UserId = @UserId
             UNION ALL
             --outer
             SELECT e.ParentArchiveId ,e.[Id], D.PermissionId, UserId, Level+1 --switched parent/child
             FROM Archives AS E 
             INNER JOIN RESULT AS D  
             ON E.Id  = D.ParentArchiveId 
        )

        SELECT TOP 1 @PermissionId = PermissionId FROM RESULT as d
        WHERE d.PermissionId is not NULL
        order by Level asc

但它不起作用。我无法理解问题出在哪里......

2 个答案:

答案 0 :(得分:1)

它不起作用,因为递归CTE的“锚点”部分不返回任何行。您希望先获取层次结构,然后查看权限:

with ancestors as (
      select id, id as parentarchiveid, 0 as level
      from archives a
      where id = @ArchiveId
      union all
      select anc.id, a.parentarchiveid, level + 1
      from ancestors anc join
           archives a
           on anc.id = a.parentarchiveid
    )
select TOP 1 @PermissionId = PermissionId
from ancestors a join
     archivepermissions ap
     on a.parentarchiveid = ap.archiveid and
        ap.userid = @UserId
order by level asc;

答案 1 :(得分:0)

            ;WITH Ancestors
        AS
        (
             SELECT E.[Id], E.ParentArchiveId, 0 as Level -- , A.PermissionId, UserId ,0 AS Level
             FROM Archives AS E  
             WHERE E.Id = @DocItemArchiveId
             UNION ALL
             SELECT a.Id , a.[ParentArchiveId], Level + 1  --, D.PermissionId, UserId, Level+1 --switched parent/child
             FROM Archives AS a 
             JOIN Ancestors AS anc  
             ON anc.ParentArchiveId  = a.Id 
             WHERE LEVEL < 10
        )

        SELECT TOP 1 @PermissionId = PermissionId FROM Ancestors as anc
        LEFT JOIN ArchivePermissions as ap ON anc.Id = ap.ArchiveId
        AND ap.UserId = @UserId
        WHERE ap.PermissionId is not NULL
        order by Level asc