2012-04-29 59 views
9

我有一個表Person有3列:Id, Name, ParentId其中ParentId是父行的IdSQL Server中的樹結構數據查詢

目前,要顯示整個樹,它必須遍歷所有子元素,直到不再有子元素。這看起來不太有效。

有更好更有效的方法來查詢這些數據嗎?

此外,有沒有更好的方式來表示這個樹像結構在SQL Server數據庫中?我的表/數據庫的另一種設計?

+0

請參閱http://stackoverflow.com/questions/935098/database-structure-for-tree-data-structure以獲得與答案類似的問題。 – JeremyDWill 2012-04-29 04:32:22

+1

請參閱Bill Karwin的[SQL反模式反擊](http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back)幻燈片組 - 他描述了幾個反模式 - 其中包括您擁有的「樸素樹」併爲其提供可能的解決方案。他還有一本名爲[SQL Antipatterns]的好書(http://pragprog.com/book/bksqla/sql-antipatterns) - 強烈推薦! – 2012-04-29 09:17:01

回答

17

我不認爲設計有任何問題,假設您的親子關係水平有限。下面是一個使用遞歸CTE檢索關係的一個簡單的例子:

USE tempdb; 
GO 

CREATE TABLE dbo.tree 
(
    ID INT PRIMARY KEY, 
    name VARCHAR(32), 
    ParentID INT FOREIGN KEY REFERENCES dbo.tree(ID) 
); 

INSERT dbo.tree SELECT 1, 'grandpa', NULL 
UNION ALL SELECT 2, 'dad', 1 
UNION ALL SELECT 3, 'me', 2 
UNION ALL SELECT 4, 'mom', 1 
UNION ALL SELECT 5, 'grandma', NULL; 

;WITH x AS 
(
    -- anchor: 
    SELECT ID, name, ParentID, [level] = 0 
    FROM dbo.tree WHERE ParentID IS NULL 
    UNION ALL 
    -- recursive: 
    SELECT t.ID, t.name, t.ParentID, [level] = x.[level] + 1 
    FROM x INNER JOIN dbo.tree AS t 
    ON t.ParentID = x.ID 
) 
SELECT ID, name, ParentID, [level] FROM x 
ORDER BY [level] 
OPTION (MAXRECURSION 32); 
GO 

不要忘了清理:

DROP TABLE dbo.tree; 

This might be a useful article.另一種方法是hierarchyid,但我覺得這對於大多數情況過於複雜。

+1

根據樹的結構,它與主題無關,但不是你的'媽媽'和'爸爸'兄弟姐妹嗎? :)我的意思是每天的生活意義,就像他們有同樣的父親。哦,沒關係 – 2016-06-07 08:58:07

+0

@Varvara是的,當然。 – 2016-06-07 14:17:21

4

亞倫Bertrands的答案是非常好的一般情況下。如果您只需要一次顯示整棵樹,則可以查詢整個表並在內存中執行樹構建。這可能更加方便和靈活。性能也會稍微好一些(無論如何,整個表都需要下載,C#比SQL Server更快)。

如果你只需要樹的一部分,不建議使用這種方法,因爲你會下載比需要更多的數據。