递归 CTE 检查记录是否存在于任何级别然后获取所有子项(文件夹结构)

Recursive CTE check if record exists at any level then get all children (folder structure)

我正在尝试使用递归 CTE 检查用户是否有权访问某个文件夹,如果他们有权访问该文件夹,则该文件夹和所有子文件夹

结构基本

CREATE TABLE [dbo].[Folders](
  [Id] [int] IDENTITY(1,1) NOT NULL,
  [Name] [nvarchar](1024) NOT NULL,
  [ParentId] [int] NULL)

这是将用户链接到文件夹的table

CREATE TABLE [dbo].[FolderAccess](
  [Id] [int] IDENTITY(1,1) NOT NULL,
  [UserId] [bigint] NOT NULL,
  [FolderId] [int] NOT NULL)

使用以下示例数据

SELECT * FROM Folders

Id ParentId Name
1 NULL Root
2 1 Sub folder 1
3 2 Sub folder 2
4 3 Sub folder 3
5 4 Sub folder 4
6 5 Sub folder 5

SELECT UserId, FolderId FROM FolderAccess

UserId FolderId
1 3

上面的用户可以访问文件夹 3,因此可以间接访问文件夹 4,5,6

我应该能够放置任何 FolderId 3,4,5,6 并获得结果,但是使用文件夹 ID 2 将 return 什么都没有,因为它在层次结构中更高。

DECLARE @FolderId INT = 3
;WITH TopDownFolderHierarchy (Id, ParentId , Name)
AS
(
    SELECT fold.Id, fold.ParentId, fold.Name FROM Folders fold 
    WHERE fold.ID = @FolderId
    UNION ALL
    SELECT parents.Id, parents.ParentId, parents.Name FROM Folders parents 
    INNER JOIN TopDownFolderHierarchy cte on cte.Id = parents.ParentId
    
)

谢谢

下面的查询首先尝试列出用户有权访问的文件夹,然后是可访问文件夹之间所需的层次结构

DECLARE @UserId INT = 1;
DECLARE @FolderId INT = 5;

WITH
AccessibleHierarchy (Id, ParentId , Name) AS
(
    SELECT fold.Id, fold.ParentId, fold.Name FROM Folders fold 
    WHERE fold.[CreatorUserId] = @UserId or fold.ID in (select [FolderId] from [FolderAccess] where [UserId] = @UserId)
    UNION ALL
    SELECT parents.Id, parents.ParentId, parents.Name FROM Folders parents 
    INNER JOIN AccessibleHierarchy cte on cte.Id = parents.ParentId
),
QueriedHierarchy (Id, ParentId , Name) AS
(
    SELECT distinct fold.Id, fold.ParentId, fold.Name FROM AccessibleHierarchy fold 
    WHERE fold.ID = @FolderId
    UNION ALL
    SELECT parents.Id, parents.ParentId, parents.Name FROM Folders parents 
    INNER JOIN QueriedHierarchy cte on cte.Id = parents.ParentId
)
select * from QueriedHierarchy

db<>fiddle

编辑:在文件夹中添加了 CreatorUserId 列的使用,并在 QueriedHierarchy 中添加了不同的关键字,以防多个 CreatorUserId/FolderAccess

允许层次结构