2012-01-16 46 views
5

Hiện nay chúng tôi có một thủ tục lưu trữ mà trả về dữ liệu từ một bảng trong đó là sơ đồ ban đầu bằng cách làm một cái gì đó như thế này:Làm thế nào để giới hạn độ sâu đệ quy CTE nhưng chọn bảng chung?

WITH CTE AS 
(
    -- Start CTE off by selecting the id that was provided to stored procedure. 
    SELECT * 
    FROM [dbo].[TestTable] 
    WHERE [Id] = 1 
    -- Recursively add tasks that are children of records already found in previous iterations. 
    UNION ALL 
    SELECT t.* 
    FROM [dbo].[TestTable] as t 
    INNER JOIN CTE as tcte 
     ON t.[ParentId] = tcte.[Id] 
)   
SELECT * 
FROM CTE 

này là tốt đẹp, bởi vì không có vấn đề thay đổi sơ đồ bảng, miễn là có cách [ Id] và [ParentId] cột, tôi sẽ không phải cập nhật thủ tục được lưu trữ này. Tôi muốn làm một cái gì đó tương tự, nhưng cũng có thể xác định chiều sâu của đệ quy động. Cách duy nhất tôi đã nhìn thấy để làm điều này là thêm một tốt nghiệp/Thực nhận dạng sâu như vậy:

WITH CTE AS 
(
    -- Start CTE off by selecting the task that was provided to stored procedure. 
    SELECT *, 0 as [Level] 
    FROM [dbo].[TestTable] 
    WHERE [Id] = 1 
    -- Recursively add tasks that are children of parent tasks that have already been found in previous iterations. 
    UNION ALL 
    SELECT t.*, [Level] + 1 
    FROM [dbo].[TestTable] as t 
    INNER JOIN CTE as tcte 
     ON t.[ParentId] = tcte.[Id] 
    WHERE [Level] < 2 
)   
SELECT * 
FROM CTE 

này hoạt động tốt, nhưng mất đi những lợi thế lớn của truy vấn trước đó kể từ khi chọn * ở cuối sẽ cho tôi là cấp độ. Có cách nào khác để làm điều này, nơi tôi có thể chỉ định một mức độ, nhưng cũng thường chọn tất cả các cột từ bảng? Cảm ơn trước.

Trả lời

12

Nếu tất cả các bạn muốn làm gì với lĩnh vực trình độ của bạn là giới hạn số lượng recursions, bạn sẽ có thể sử dụng một MAXRECURSION query hint, một cái gì đó như thế này:

WITH Department_CTE AS 
(
    SELECT 
     DepartmentGroupKey, 
     ParentDepartmentGroupKey, 
     DepartmentGroupName 
    FROM dimDepartmentGroup 
    WHERE DepartmentGroupKey = 2 
    UNION ALL 
    SELECT 
     Child.DepartmentGroupKey, 
     Child.ParentDepartmentGroupKey, 
     Child.DepartmentGroupName 
    FROM Department_CTE AS Parent 
     JOIN DimDepartmentGroup AS Child 
      ON Parent.ParentDepartmentGroupKey = Child.DepartmentGroupKey 
) 
SELECT * FROM Department_CTE 
OPTION (MAXRECURSION 2) 

Edit:

Trong câu trả lời cho các câu hỏi trong các ý kiến, không, bạn không thể ngăn chặn các lỗi mà bạn nhận được khi đệ quy nhiều lần hơn so với cài đặt MAXRECURSION của bạn cho phép. Nếu tôi hiểu bạn một cách chính xác, bạn có thể làm một cái gì đó như thế này:

WITH CTE AS 
(
    -- Start CTE off by selecting the task that was provided to stored procedure. 
    SELECT Id, 0 as [Level] 
    FROM [dbo].[TestTable] 
    WHERE [Id] = 1 
    -- Recursively add tasks that are children of parent tasks that have already been found in previous iterations. 
    UNION ALL 
    SELECT t.Id, [Level] + 1 
    FROM [dbo].[TestTable] as t 
    INNER JOIN CTE as tcte 
     ON t.[ParentId] = tcte.[Id] 
    WHERE [Level] < 2 
), 
CTE2 AS 
(
    SELECT TestTable.* 
    FROM CTE 
     INNER JOIN TestTable ON CTE.Id = TestTable.Id 
) 
SELECT * FROM CTE2; 

này cần được bình đẳng như quát như những gì bạn có ở trên, giả sử bạn đang không có kế hoạch về việc thay đổi các lĩnh vực then chốt thứ bậc hay tiểu học.

+0

Điều đó có vẻ như đã xảy ra lỗi khi đạt đến giới hạn. Có cách nào để dừng nó dựa trên MAXRECURSION, nhưng tiếp tục sử dụng kết quả? – Ocelot20

+0

Đã trả lời ở trên (có đề xuất khác) ... – mwigdahl

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