Sql server 列中ID列表上的SQL联接
我的数据库中有一个名为MyFolder的多层对象。MyFolder可以是另一个无限级别MyFolder的子级。该表定义如下:Sql server 列中ID列表上的SQL联接,sql-server,tsql,Sql Server,Tsql,我的数据库中有一个名为MyFolder的多层对象。MyFolder可以是另一个无限级别MyFolder的子级。该表定义如下: CREATE TABLE dbo.MyFolders ( MyFolderId INT IDENTITY(1,1) NOT NULL, ParentMyFolderId INT NULL, Name NVARCHAR(50) NOT NULL, Depth INT NOT NULL, Ancestry NVARCHAR(max) N
CREATE TABLE dbo.MyFolders
(
MyFolderId INT IDENTITY(1,1) NOT NULL,
ParentMyFolderId INT NULL,
Name NVARCHAR(50) NOT NULL,
Depth INT NOT NULL,
Ancestry NVARCHAR(max) NOT NULL,
CONSTRAINT PK_MyFolders PRIMARY KEY CLUSTERED (MyFolderId ASC),
CONSTRAINT FK_MyFolders_MyFolders FOREIGN KEY(ParentMyFolderId) REFERENCES dbo.MyFolders (MyFolderId)
)
它有如下数据:
MyFolderId ParentMyFolderId Name Depth Ancestry
1 NULL Folder1 0 /
2 1 Folder1A 1 /1/
3 1 Folder1B 1 /1/
4 1 Folder1C 1 /1/
5 4 Folder1C1 2 /1/4/
6 4 Folder1C2 2 /1/4/
7 6 Folder1C2a 3 /1/4/6/
8 6 Folder1C2b 3 /1/4/6/
这对于我的系统中所需的一切都非常有效。但是,如果要检索如下查询,则会变得很棘手:
MyFolderId Name
1 Folder1
2 Folder1/Folder1A
3 Folder1/Folder1B
4 Folder1/Folder1C
5 Folder1/Folder1C/Folder1C1
6 Folder1/Folder1C/Folder1C2
7 Folder1/Folder1C/Folder1C2/Folder1C2a
8 Folder1/Folder1C/Folder1C2/Folder1C2b
有没有办法加入祖先场以获得祖先的名字?还是使用ParentMyFolderId列的另一种方法?我确实有一个名为SplitString(value,delimiter)的表值拆分字符串函数。这可以使用递归查询来完成,只需将当前文件夹名称附加到以前的文件夹中即可 查询:
;WITH Source (MyFolderId, ParentMyFolderId, Name, Depth, Ancestry)
AS (
SELECT 1, NULL, 'Folder1', 0, '/'
UNION ALL
SELECT 2, 1, 'Folder1A', 1, '/1/'
UNION ALL
SELECT 3, 1, 'Folder1B', 1, '/1/'
UNION ALL
SELECT 4, 1, 'Folder1C', 1, '/1/'
UNION ALL
SELECT 5, 4, 'Folder1C1', 2, '/1/4/'
UNION ALL
SELECT 6, 4, 'Folder1C2', 2, '/1/4/'
UNION ALL
SELECT 7, 6, 'Folder1C2a', 3, '/1/4/6/'
UNION ALL
SELECT 8, 6, 'Folder1C2b', 3, '/1/4/6/'
),
cte AS
(
SELECT S.MyFolderID, S.ParentMyFolderId, CAST(S.Name AS VARCHAR(MAX)) AS Name
FROM Source AS S
WHERE ParentMyFolderId IS NULL
UNION ALL
SELECT S.MyFolderID, S.ParentMyFolderId, C.Name + '/' + S.Name
FROM Source AS S
INNER JOIN cte AS C
ON C.MyFolderId = S.ParentMyFolderId
)
SELECT *
FROM cte
下面是注释中提到的递归CTE:
WITH TreeStructure(MyFolderId, Name) AS
(
SELECT MyFolderId, CONVERT(varchar(500), Name)
FROM MyFolders WHERE ParentMyFolderId IS NULL
UNION ALL
SELECT sd.MyFolderId, CONVERT(varchar(500), t.Name + '/' + sd.Name)
FROM MyFolders sd
JOIN TreeStructure t ON sd.ParentMyFolderId = t.MyFolderId
WHERE sd.ParentMyFolderId IS NOT NULL
)
SELECT * FROM TreeStructure
结果:
MyFolderId名称
----------- ----------------------------------------
1文件夹1
2折叠1/折叠1a
3文件夹1/文件夹1b
4折叠1/折叠1c
5文件夹1/文件夹1C/文件夹1C1
6文件夹1/文件夹1C/文件夹1C2
7文件夹1/文件夹1C/文件夹1C2/文件夹1C2A
8文件夹1/文件夹1C/文件夹1C2/文件夹1C2B
递归cte应该能够非常轻松地完成您想要的操作。只是好奇——您是否考虑过将祖先
列切换为hierarchyid
类型?这将为您提供一些引用完整性,这样您就不必担心无效的祖先值(例如/1/4/17
)。