给表结构,如:
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
我在SO上看过类似的问题,但大多数情况下他们似乎只是在看一定数量的关卡。
这种结构最终可能是无限的 - 带有孩子的文件夹,以及许多其他孩子
这可能吗?如果是这样,我将如何完成它?
答案 0 :(得分:3)
所以引用这个答案:
<强> Sql Server CTE Parent Child recursive 强>
以下是您的架构的工作版本:
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')
;
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
,这不会限制数量水平。
答案 1 :(得分:0)
您需要的是递归查询。 This Microsoft Technet example完全符合您的要求,但在示例中,我们要求的是员工层次结构,而不是文件夹。
从链接页面:
-- 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