2012-02-03 24 views
10

xem xét dưới đâyTại sao chúng ta không thể sử dụng các kết nối bên ngoài trong CTE đệ quy?

;WITH GetParentOfChild AS 
    (
     SELECT 
      Rn = ROW_NUMBER() Over(Order By (Select 1)) 
      ,row_id AS Parents 
      ,parent_account_id As ParentId 
     FROM siebelextract..account 
     WHERE row_id = @ChildId 
     UNION ALL 
     SELECT 
      Rn + 1 
      ,a.row_id as Parents 
      ,a.parent_account_id As ParentId  
     FROM siebelextract..account a 
     JOIN GetParentOfChild gp on a.row_id = gp.ParentId 
    ) 

SELECT TOP 1 @ChildId = Parents 
FROM GetParentOfChild 
ORDER BY Rn DESC 

gì nó là đưa ra bất kỳ đứa trẻ, nó sẽ trở lại phụ huynh cấp cơ .... Chương trình được hoàn toàn làm việc tốt tất cả các thời gian ...

Chỉ cần ra khỏi tò mò/lợi ích thực nghiệm tôi đã thay đổi JOIN để Left Outer Join và nó báo cáo

Msg 462, Level 16, State 1, Thủ tục GetParent, dòng 9 Outer join không được phép trong phần đệ quy của một bảng thông thường đệ quy biểu thức 'GetParentOfChild'.

Câu hỏi của tôi là lý do tại sao phần đệ quy của CTE không thể chấp nhận Tham gia bên ngoài trái? Có phải do thiết kế?

Cảm ơn

Trả lời

6

Vâng, đó là do thiết kế, đọc Guidelines for Defining and Using Recursive Common Table Expressions

Các mục sau đây được không được phép trong CTE_query_definition của một thành viên đệ quy:

  • SELECT DISTINCT
  • GROUP BY
  • tập hợp vô hướng
  • TOP
  • trái, sang phải, OUTER JOIN (INNER JOIN được phép)
  • các truy vấn con

Chú ý rằng nếu truy vấn của bạn làm cho một trái tham gia với nó thông qua CTE có thể trở thành một đệ quy vô hạn.

+8

Tôi không nghĩ câu trả lời này hoặc liên kết thực sự trả lời "tại sao". Tôi muốn kết hợp hai phép nối trái (với các bảng bên ngoài) để kiểm soát hướng của phép lặp tiếp theo chẳng hạn. Việc đệ quy vô hạn dường như không phải là lý do chính đáng để từ bỏ tất cả các vòng lặp. – crokusek

+3

@crokusek, chuẩn bị truy vấn kết hợp của bạn trong một expresion cte trước đó và bên trong tham gia nó vào truy vấn cte đệ quy của bạn. – danihp

+0

Ha, tôi đã thử nó và nó chạy, lừa gọn gàng. Nếu tôi đã làm đúng, tôi phải chuyển đổi các phép nối trái sang bên ngoài hoàn toàn trong cte. Nó chạy nhưng kế hoạch truy vấn trở nên khốn khổ - nó tính toán toàn bộ bên ngoài hoàn toàn trước khi bắt đầu trên rte (sẽ không kết thúc, tùy thuộc vào kích thước), mất tính độc đáo của đệ quy thăm dò chỉ chính xác những gì nó cần. Một con trỏ sẽ thực hiện trừ khi kết quả cte nhỏ. Có lẽ một cách giải quyết tốt cho một số trường hợp dù sao đi nữa. – crokusek

8

Bạn không thể sử dụng LEFT JOIN với CTE đệ quy nhưng bạn có thể sử dụng OUTER APPLY để đưa ra kết quả tương tự.

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