我不确定我是否完全理解你想要做什么。如果您需要一个层次结构,您应该使用一个名为“Levels”的表,并将您的所有级别信息都放在该表中。你不需要4张桌子。您可以执行自加入以轻松返回父信息。
问题在于,为了在链条中移动,您可能必须使用某种循环。这通常在 SQL 语句中避免,因为查询优化器必须为循环的每次迭代生成一个执行计划(这是低效的)。可以只使用 SQL,但我建议提取包含所有信息的表,并使用不适合基于集合的操作的非 SQL 编程语言对其进行解析。
下面是一些示例代码,它使用一个表来处理所有 4 个级别。在表中构建树后,您只需要通过 FOR 循环来显示您想要的方式。
--Creates Temp table (This table will expire upon connection close)
CREATE TABLE [#Levels] ([id] INT, [name] NVARCHAR(256), [level] INT, [idFather] INT);
--Populate Temp table with some sample data
INSERT INTO #Levels VALUES (1,'AbsoluteParent',1,null)
INSERT INTO #Levels VALUES (2,'ChildItem1',2,1)
INSERT INTO #Levels VALUES (3,'ChildItem2',2,1)
INSERT INTO #Levels VALUES (4,'GrandChild',3,2)
--Display populated table
SELECT * FROM [#Levels]
--Create 2 instances of our Temp table and join (id > idFather) so that we can return information about the parent table.
SELECT [T1].[name] AS 'Name'
, [T2].[name] AS 'Parent Name'
FROM [#Levels] AS T1
LEFT JOIN [#Levels] T2 ON [T1].[idFather] = [T2].[id]
--We can even link another instance of our Temp table and give information about grandparents!
SELECT [T1].[name] AS 'Name'
, [T2].[name] AS 'Parent Name'
, [T3].[name] AS 'Grand Parent Name'
FROM [#Levels] AS T1
LEFT JOIN [#Levels] T2 ON [T1].[idFather] = [T2].[id]
LEFT JOIN [#Levels] T3 ON [T2].[idFather] = [T3].[id]
也许您正在寻找的是一个递归公用表表达式,它将输出反馈给函数以递归地显示所有子项。这是一个微软的例子:https://technet.microsoft.com/en-us/library/ms186243(v=sql.105).aspx
我稍微简化了微软的例子:
-- Create a temp Employee table.
CREATE TABLE #MyEmployees
(
EmployeeID smallint NOT NULL,
FirstName nvarchar(30) NOT NULL,
LastName nvarchar(40) NOT NULL,
Title nvarchar(50) NOT NULL,
ManagerID int NULL,
);
-- Populate the table with values.
INSERT INTO #MyEmployees VALUES
(1, N'Ken', N'Sánchez', N'Chief Executive Officer',NULL)
,(273, N'Brian', N'Welcker', N'Vice President of Sales',1)
,(274, N'Stephen', N'Jiang', N'North American Sales Manager',273)
,(275, N'Michael', N'Blythe', N'Sales Representative',274)
,(276, N'Linda', N'Mitchell', N'Sales Representative',274)
,(285, N'Syed', N'Abbas', N'Pacific Sales Manager',273)
,(286, N'Lynn', N'Tsoflias', N'Sales Representative',285)
,(16, N'David',N'Bradley', N'Marketing Manager',273)
,(23, N'Mary', N'Gibson', N'Marketing Specialist',16);
WITH DirectReports (ManagerID, EmployeeID, Title, Level)
AS
(
SELECT e.ManagerID, e.EmployeeID, e.Title, 0 AS Level
FROM #MyEmployees AS e
WHERE e.ManagerID is null
UNION ALL
SELECT e.ManagerID, e.EmployeeID, e.Title, d.Level + 1
FROM #MyEmployees AS e
INNER JOIN DirectReports AS d
ON e.ManagerID = d.EmployeeID
)
SELECT ManagerID, EmployeeID, Title, Level
FROM DirectReports