2012-04-29 64 views
9

Tôi có một bảng Person có 3 cột: Id, Name, ParentId trong đó ParentIdId của hàng chính.Truy vấn dữ liệu cấu trúc cây trong SQL Server

Hiện tại, để hiển thị toàn bộ cây, nó sẽ phải lặp qua tất cả các phần tử con cho đến khi không còn phần tử con nào nữa. Nó có vẻ không hiệu quả lắm.

Có cách nào tốt hơn và hiệu quả hơn để truy vấn dữ liệu này không?

Ngoài ra, có cách nào tốt hơn để đại diện cho cây này như cấu trúc trong cơ sở dữ liệu SQL Server không? Một thiết kế thay thế cho bảng/cơ sở dữ liệu của tôi?

+0

Xem http://stackoverflow.com/questions/935098/database-structure-for-tree-data-structure cho câu hỏi tương tự với câu trả lời. – JeremyDWill

+1

Xem bài viết về trang trình bày [SQL Antipatterns] (http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back) của Bill Karwin - ông mô tả một số antipatterns - trong số đó là "cây ngây thơ" mà bạn có - và đưa ra các giải pháp khả thi cho nó. Ông cũng có một cuốn sách tuyệt vời cùng tên [SQL Antipatterns] (http://pragprog.com/book/bksqla/sql-antipatterns) - rất khuyến khích! –

Trả lời

17

Tôi không nghĩ có gì sai với thiết kế, giả sử bạn có một mức độ hạn chế về mối quan hệ cha-con. Dưới đây là một ví dụ nhanh thu hồi mối quan hệ sử dụng một CTE đệ quy:

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 

Đừng quên để làm sạch:

DROP TABLE dbo.tree; 

This might be a useful article. Một cách khác là hierarchyid nhưng tôi thấy nó quá phức tạp đối với hầu hết các kịch bản .

+1

Nó không liên quan đến chủ đề, nhưng không phải là 'mẹ' và 'anh chị em' của bạn, theo cấu trúc cây của bạn? :) Ý tôi là ý nghĩa sống hàng ngày, giống như họ có cùng một người cha. Ồ, đừng bận tâm –

+0

@Varvara Yeah, chắc chắn rồi. –

4

Câu trả lời của Aaron Bertrands rất tốt cho trường hợp chung. Nếu bạn chỉ cần hiển thị toàn bộ cây cùng một lúc, bạn chỉ có thể truy vấn toàn bộ bảng và thực hiện việc xây dựng cây trong bộ nhớ. Điều này có thể thuận tiện và linh hoạt hơn. Hiệu suất cũng sẽ tốt hơn một chút (toàn bộ bảng cần được tải xuống và C# nhanh hơn cho các phép tính như vậy so với SQL Server).

Nếu bạn chỉ cần một phần của cây, phương pháp này không được khuyến nghị vì bạn sẽ tải xuống nhiều dữ liệu hơn mức cần thiết.

Các vấn đề liên quan