把桌上的结构,是这样的:
ID ParentID Name
1 NULL A root
2 NULL Another root
3 1 Child of 1
4 3 Grandchild of 1
5 4 Great grandchild of 1
6 1 Child of 1
7 NULL Another root
8 7 Child of 6
给出的,当我在寻找一个优雅的(如果可能)的解决方案单个SQL语句/函数将返回表中的所有数据ID = 1
所以,我的结果看起来是这样的:
ID ParentID Name
1 NULL A root
3 1 Child of 1
4 3 Grandchild of 1
5 4 Great grandchild of 1
6 1 Child of 1
我已经看到了这样类似的问题,虽然在大多数情况下,他们似乎只是在看水平的给定数。
这种结构可以最终是无限的 - 有孩子的文件夹,与许多其他的孩子
这可能吗? 如果是的话,我会怎么做到的呢?
所以引用这个答案:
SQL Server的CTE亲子递归
这里是你的架构工作版本:
表创建脚本
CREATE TABLE YOUR_TABLE
([ID] int, [ParentID] int, [Name] varchar(21))
;
INSERT INTO YOUR_TABLE
([ID], [ParentID], [Name])
VALUES
(1, NULL, 'A root'),
(2, NULL, 'Another root'),
(3, 1, 'Child of 1'),
(4, 3, 'Grandchild of 1'),
(5, 4, 'Great grandchild of 1'),
(6, 1, 'Child of 1'),
(7, NULL, 'Another root'),
(8, 7, 'Child of 6')
;
递归CTE
DECLARE @ID INT = 1
;WITH ParentChildCTE
AS (
SELECT ID, ParentId, Name
FROM YOUR_TABLE
WHERE Id = @ID
UNION ALL
SELECT T1.ID, T1.ParentId, T1.Name
FROM YOUR_TABLE T1
INNER JOIN ParentChildCTE T ON T.ID = T1.ParentID
WHERE T1.ParentID IS NOT NULL
)
SELECT *
FROM ParentChildCTE
关键部分是在CTE
创作,其中UNION ALL
加入回结果集,加盟ID
来ParentId
,即不限制级别的数量。
你需要的是一个递归查询。 此Microsoft TechNet例如不正是你想要的,但在这个例子中,我们要为员工,而不是文件夹的层次结构。
从链接页面:
-- Create an Employee table.
CREATE TABLE dbo.MyEmployees
(
EmployeeID smallint NOT NULL,
FirstName nvarchar(30) NOT NULL,
LastName nvarchar(40) NOT NULL,
Title nvarchar(50) NOT NULL,
DeptID smallint NOT NULL,
ManagerID int NULL,
CONSTRAINT PK_EmployeeID PRIMARY KEY CLUSTERED (EmployeeID ASC)
);
-- Populate the table with values.
INSERT INTO dbo.MyEmployees VALUES
(1, N'Ken', N'Sánchez', N'Chief Executive Officer',16,NULL)
,(273, N'Brian', N'Welcker', N'Vice President of Sales',3,1)
,(274, N'Stephen', N'Jiang', N'North American Sales Manager',3,273)
,(275, N'Michael', N'Blythe', N'Sales Representative',3,274)
,(276, N'Linda', N'Mitchell', N'Sales Representative',3,274)
,(285, N'Syed', N'Abbas', N'Pacific Sales Manager',3,273)
,(286, N'Lynn', N'Tsoflias', N'Sales Representative',3,285)
,(16, N'David',N'Bradley', N'Marketing Manager', 4, 273)
,(23, N'Mary', N'Gibson', N'Marketing Specialist', 4, 16);
然后
WITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level)
AS
(
-- Anchor member definition
SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
0 AS Level
FROM dbo.MyEmployees AS e
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL
WHERE ManagerID IS NULL
UNION ALL
-- Recursive member definition
SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
Level + 1
FROM dbo.MyEmployees AS e
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL
INNER JOIN DirectReports AS d
ON e.ManagerID = d.EmployeeID
)
-- Statement that executes the CTE
SELECT ManagerID, EmployeeID, Title, DeptID, Level
FROM DirectReports
INNER JOIN HumanResources.Department AS dp
ON DirectReports.DeptID = dp.DepartmentID
WHERE dp.GroupName = N'Sales and Marketing' OR Level = 0;
GO
检查结果是
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
NULL 1 Chief Executive Officer 0
1 273 Vice President of Sales 1
273 16 Marketing Manager 2
273 274 North American Sales Manager 2
273 285 Pacific Sales Manager 2
16 23 Marketing Specialist 3
274 275 Sales Representative 3
274 276 Sales Representative 3
285 286 Sales Representative 3