2009-05-29 41 views
3

我有一個遞歸表,其中每個記錄都有一個ID和一個PARENTID。 PARENTID指向同一個表中的不同ID。 SQL Server中有沒有一種方法可以在一個語句中選擇整個「樹」?我可以編寫一個遞歸函數來從父項跳轉到所有子項,但是我想用一種方法在一個查詢中完成。在SQL Server中,如何選擇遞歸表中的所有記錄?

在Oracle中,它應該是這樣的:

select 
    id, 
    parentid, 
    nodename 
from 
    MY_SCHEMA.MY_TABLE 
    connect by nocycle prior parentid = id 
start with id = :starting_id_number 
order by 
    id 

什麼會在SQL Server相當於是什麼?

回答

3

這裏是我爲你們一起扔的一個例子。它演示了使用遞歸公用表表達式(CTE)。

CREATE TABLE #tempTable 
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY, 
    parentID INT NULL 
) 

INSERT INTO #tempTable (parentID) VALUES (null) 
INSERT INTO #tempTable (parentID) VALUES (1) 
INSERT INTO #tempTable (parentID) VALUES (1) 
INSERT INTO #tempTable (parentID) VALUES (2) 
INSERT INTO #tempTable (parentID) VALUES (3) 
INSERT INTO #tempTable (parentID) VALUES (2) 
INSERT INTO #tempTable (parentID) VALUES (5) 


SELECT * FROM #tempTable; 

WITH RecursiveTable (ID, ParentID, Level) 
AS 
(
    --Anchor 
    SELECT tt.ID, 
      tt.ParentID, 
      0 AS Level 
    FROM #tempTable AS tt 
    WHERE parentID IS null 
    UNION ALL 
    --Recursive member definition 
    SELECT tt.ID, 
      tt.ParentID, 
      LEVEL + 1 
    FROM #tempTable AS tt 
     INNER JOIN RecursiveTable rt ON 
     tt.ParentID = rt.ID 
) 
SELECT * 
FROM RecursiveTable 

DROP TABLE #tempTable 

編輯:作爲一個額外的想法,在SQL Server 2008中有一個數據類型,稱爲HIERARCHYID可用於實現分層數據結構。請參見下面的教程

http://technet.microsoft.com/en-us/library/bb677213.aspx

+0

這爲我工作,但我必須說,這是做這種事情相當鈍的方式。 – JosephStyons 2009-05-29 15:40:54

0

身份證也有這個問題,但我沒有找到解決辦法。 所以我創建了這個解決方法: 我添加了一個新列'tree_id',以便我的表看起來像這樣。

treeid|id|parentid|nodename 
1  |1 | null | rootOfTreeOne 
1  |2 | 1  | childOfRootOne 
1  |3 | 1  | secondChild 
2  |4 | null | rootOfSecondTree 
2  |5 | 4  | childofSecondTree 

並在程序中創建樹。優點是可以用一個簡單的單一select語句從樹中獲取所有節點。

select * from tree_table where tree_id = 1; 

但也有一些存儲過程可以幫助您解決您的問題。

希望這有助於..

0

我不認爲你可以逃脫它,而無需在語句中使用遞歸。

如果你能夠(或者將來參考),你可以嘗試使用modified preorder tree traversal,這將允許你這樣做。

在此答案中解釋修改過的預定義樹遍歷不在範圍之內,因爲它需要一些解釋和播放才能掌握。

我會指出,在MPTT上有更新和插入記錄的開銷,但選擇通常效率更高。在一般情況下,選擇發生了一大堆比更新/插入更何況它是值得的,但它是值得擁有直在想一下潛水前你的特殊情況。

我掛我找到一個很好的解釋文章MPTT。

0

您應該可以使用公用表表達式來執行遞歸查詢。做一個谷歌搜索「遞歸查詢使用通用表表達式」,有一個MSDN文章。

嘆息新用戶不允許添加超鏈接。

1

您可以使用CTE的這樣;

CREATE TABLE TestTable 
( 
    ID int primary key NOT NULL, 
    ParentID int 
) 

INSERT INTO TestTable VALUES (0, null) 
INSERT INTO TestTable VALUES (1, 0) 
INSERT INTO TestTable VALUES (2, 0) 
INSERT INTO TestTable VALUES (3, 1) 
INSERT INTO TestTable VALUES (4, 3) 


-- Get branch 
;WITH TreeRecCTE (ID, ParentID, IDPath) 
AS 
(
    SELECT ID, ParentID, CONVERT(varchar(max), ID) As IDPath 
     FROM TestTable 
     WHERE ParentID IS NULL 
    UNION ALL 
    SELECT 
      Child.ID, 
      Child.ParentID, 
      Parent.IDPath + '.' + CONVERT(varchar(100),Child.ID) As IDPath 
     FROM TestTable As Child INNER JOIN TreeRecCTE AS Parent ON Child.ParentID = Parent.ID 
) 
SELECT * FROM TreeRecCTE WHERE IDPath LIKE '%.1.%' ORDER BY ParentID ASC 


-- Get complete tree: 
;WITH TreeRecCTE (ID, ParentID, IDPath) 
AS 
(
    SELECT ID, ParentID, CONVERT(varchar(max), ID) As IDPath 
     FROM TestTable 
     WHERE ParentID IS NULL 
    UNION ALL 
    SELECT 
      Child.ID, 
      Child.ParentID, 
      Parent.IDPath + '.' + CONVERT(varchar(100),Child.ID) As IDPath 
     FROM TestTable As Child INNER JOIN TreeRecCTE AS Parent ON Child.ParentID = Parent.ID 
) 
SELECT * FROM TreeRecCTE ORDER BY ParentID ASC 
相關問題