2012-02-09 83 views
3

SQL顶级父记录我有一个表结构:在层次

CompanyID,公司名称,LinkedCompanyID

使多个企业能在一个层次链接

例如

CompanyID, CompanyName, LinkedCompanyID 
1   Company A, NULL 
2   Company B, 1 
3   Company C, 2 
4   Company D, 2 
5   Company E, 4 
6   Company F, 3 
7   Company G, NULL 

我想查询返回每个公司

CompanyID, CompanyName, ToplevelParentID 
1   Company A, NULL (or 1 I don't mind) 
2   Company B, 1 
3   Company C, 1 
4   Company D, 1 
5   Company E, 1 
6   Company F, 1 
7   Company G, NULL (or 7 I don't mind) 

我在使用recusive CTE表达式采取一脸的顶级父,但所有的例子我可以从父母而不是最上面的父母中找到返回分层列表。

大家能否请提供任何指针或样本查询

+2

强烈建议:添加一个字段跟踪“顶级容器”。我在类似的场景中做了这些(并且一些intent knwdes是他们自己的容器 - 例如CMS:folter被结构化为文档,这是一个容器,然后是文档中的结构,这使得更容易。 – TomTom 2012-02-09 13:13:24

回答

6

这仍然可以用递归CTE实现:

CREATE TABLE #Test (CompanyID INT, CompanyName VARCHAR(20), LinkedCompanyID INT) 
INSERT INTO #Test 
SELECT 1, 'Company A', NULL UNION 
SELECT 2, 'Company B', 1 UNION 
SELECT 3, 'Company C', 2 UNION 
SELECT 4, 'Company D', 2 UNION 
SELECT 5, 'Company E', 4 UNION 
SELECT 6, 'Company F', 3 UNION 
SELECT 7, 'Company G', NULL 

;WITH CTE AS 
( SELECT *, 0 [Level] 
    FROM #Test 
    UNION ALL 
    SELECT CTE.CompanyID, CTE.CompanyName, #Test.LinkedCompanyID, Level + 1 
    FROM CTE 
      INNER JOIN #Test 
       ON CTE.LinkedCompanyID = #Test.CompanyID 
    WHERE #Test.LinkedCompanyID IS NOT NULL 
) 

SELECT c.CompanyID, c.CompanyName, c.LinkedCompanyID 
FROM ( SELECT *, MAX([Level]) OVER (PARTITION BY CompanyName) [MaxLevel] 
      FROM CTE 
     ) c 
WHERE MaxLevel = Level 

DROP TABLE #Test 
+0

这是完美的。使用CROSS APPLY和CTE我了解CTE的一部分,你介意解释交叉应用的作用 – fujih 2012-02-09 13:20:25

+0

最后一个查询只是得到CTE最后一次递归所插入的行。这可以实现(INNER JOIN,EXISTS),但我认为在这种情况下使用OVER函数是最有效的方法,如果您选择* FROM CTE,您应该更好地了解最终查询如何限制输出到顶级公司。子查询C仅用于因为窗口函数不能出现在WHERE子句中。 – GarethD 2012-02-09 13:35:54

-1

试试这个:

Select * , (select CompanyName from Company C_aux where C_Main.LinkedCompanyID = C_aux.CompanyID) as ToplevelParentID 
from Company C_Main 
+0

谢谢,但只返回最接近的父级而不是顶级父级 – fujih 2012-02-09 13:16:16

+0

忘记吧,可能不好 – Diego 2012-02-09 13:23:46