我有四张桌子,
这个逻辑允许构建一个树,其中叶子是Level4中的项目,他的父亲可以采用级别1,2或3.同样,Level3中的项目可以有一个父级位于2级o 1。
对于给定的id和级别,有任何查询可以获取下面的树,直到给定的级别?
例如,我们是否有下一个数据:
Level1 - 001,GroupEnterprise1,001,1
Level2 - 001-1,Enterprise1,001,1
Level2 - 001-2,Enterprise2,001,1
Level3 - 002-1,Enterprise3,001-1,2
Level4 - 003-1,Office 1,001-1,3
Level4 - 003-2,Office 2,2001-2,3
Level4 - 003-3,Office 3,001-2,3
Level4 - 003-4,Office 4,001-1,3
我可以咨询所有办公室(第4级的项目),即GroupEnterprise1集团的女儿,孙女和曾孙女,或Enterprise3的女儿办公室,以及GroupEnterprise1女儿的企业。
查询的参数是Id,Level和Level,直到我希望构建树。
答案 0 :(得分:0)
我不确定我是否完全明白你要做什么。如果您需要层次结构,则应使用名为“Levels”的单个表,并在该表中包含所有Level信息。你不需要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