2012-02-09 85 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