递归 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
编辑:在文件夹中添加了 CreatorUserId 列的使用,并在 QueriedHierarchy 中添加了不同的关键字,以防多个 CreatorUserId/FolderAccess
允许层次结构
我正在尝试使用递归 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
编辑:在文件夹中添加了 CreatorUserId 列的使用,并在 QueriedHierarchy 中添加了不同的关键字,以防多个 CreatorUserId/FolderAccess
允许层次结构