2012-10-24 38 views
5

Tôi có một truy vấn CTE hiển thị một cây bằng cách sử dụng đệ quy. Điều này làm việc tuyệt vời khi hiển thị toàn bộ cây. Nhưng tôi muốn truyền ID như một biến và bao gồm các anh chị em cho mỗi nút hiện tại.CTE cha mẹ và con hiển thị anh chị em

Testcode:

DECLARE @TT TABLE 
(
ID int, 
Name varchar(25), 
ParentID int, 
SortIndex int 
) 

INSERT @TT 
SELECT 1, 'A', NULL, 1 UNION ALL 
SELECT 2, 'B_1', 3, 1 UNION ALL 
SELECT 3, 'B', 1, 2 UNION ALL 
SELECT 4, 'B_2', 3, 2 UNION ALL 
SELECT 5, 'C', 1, 3 UNION ALL 
SELECT 6, 'C_2', 5, 2 UNION ALL 
SELECT 7, 'A_1', 1, 1 UNION ALL 
SELECT 8, 'A_2', 1, 2 UNION ALL 
SELECT 9, 'C_1', 5, 1 


;WITH CTETree 
AS 
(
    SELECT *, CAST(NULL AS VARCHAR(25)) AS ParentName, 1 AS Lev, 
    CAST(ROW_NUMBER() OVER(ORDER BY SortIndex) AS VARBINARY(MAX)) AS SortPath 
    FROM @TT 
    WHERE ParentID IS NULL 

    UNION ALL 

    SELECT F.*, CTETree.Name AS ParentName, Lev + 1, 
    SortPath + CAST(ROW_NUMBER() OVER(ORDER BY F.SortIndex) AS BINARY(32)) 
    FROM @TT AS F 
    INNER JOIN CTETree 
    ON F.ParentID = CTETree.ID 
) 

SELECT * FROM CTETree 
    ORDER BY SortPath 

/* 
DESIRED RESULT: 

WHEN ID = 3 PASSED IN: 

1 A NULL 1 NULL 1 
3 B 1 2 A 2 
2 B_1 3 1 B 3 
4 B_2 3 2 B 3 
5 C 1 3 A 2 

WHEN ID = 1 PASSED IN: 

1 A NULL 1 NULL 1 
3 B 1 2 A 2 
5 C 1 3 A 2 

WHEN ID = 9 PASSED IN: 

1 A NULL 1 NULL 1 
3 B 1 2 A 2 
5 C 1 3 A 2 
9 C_1 5 1 C 3 
6 C_2 5 2 C 3 

*/ 

SQL-Fiddle: http://sqlfiddle.com/#!3/d41d8/5526

+3

bạn có thể giải thích kết quả của bạn? – podiluska

+0

Ngoài ra, bạn biết SQL 2008 có một kiểu dữ liệu phân cấp cho loại điều này? – podiluska

+1

hãy giải thích rõ hơn, 'anh chị em' thường có nghĩa là anh chị em (cùng cha mẹ), nhưng kết quả của bạn cho thấy kết quả khác – fnurglewitz

Trả lời

2

Chỉ trong một lần tôi đối đầu với một câu hỏi mà biến mất A_1 và A_2. Do đó thêm vào ngoại lệ (trong trường hợp khoản). Nếu bạn cần hồ sơ này xóa biểu thức này VÀ f.ID! = 7 VÀ f.ID! = 8.

DECLARE @ID int = 3 -- variable wich you want pass 
DECLARE @Matched int = (SELECT CASE WHEN ParentID = 1 THEN ID ELSE ParentID END FROM @TT WHERE ID = @ID) 
;WITH CTETree 
AS 
(
SELECT *, CAST(NULL AS VARCHAR(25)) AS ParentName, 1 AS Lev, 
     CAST(ROW_NUMBER() OVER(ORDER BY SortIndex) AS VARBINARY(MAX)) AS SortPath, 
     0 AS Matched 
FROM @TT 
WHERE ParentID IS NULL 
UNION ALL 
SELECT F.*, cte.Name AS ParentName, cte.Lev + 1, 
     SortPath + CAST(ROW_NUMBER() OVER(ORDER BY F.SortIndex) AS BINARY(32)), 
     CASE WHEN (cte.ID = 1 AND f.ID != 7 AND f.ID != 8) 
     OR (cte.ID = @Matched AND cte.Lev + 1 > 2) 
     THEN 1 END AS Matched 
FROM @TT AS F INNER JOIN CTETree cte 
ON F.ParentID = cte.ID 
) 
SELECT ID, Name, ParentID, SortIndex, ParentName, Lev FROM CTETree 
WHERE Matched IS NOT NULL 
ORDER BY SortPath 

Demo trên SQLFiddle

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