2012-02-03 12 views
10

Rozważmy poniżejDlaczego nie możemy używać sprzężeń zewnętrznych w rekurencyjnym CTE?

;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 

co robi jest, że biorąc pod uwagę każde dziecko, zwróci poziomie głównym rodzica .... Program doskonale działa dobrze przez cały czas ...

Wystarczy się z ciekawości/wzgląd eksperymentalnej Zmieniłem JOIN LEFT OUTER JOIN i zgłaszane

Msg 462, Level 16, State 1, postępowanie getParent, Linia 9 sprzężenie zewnętrzne nie jest dozwolone w rekurencyjnego ramach cyklicznej wspólnym stole wyrażenie "GetParentOfChild".

Moje pytanie brzmi: dlaczego rekurencyjna część CTE nie może zaakceptować Left Outer Join? Czy to projekt?

Dzięki

Odpowiedz

6

Tak, to jest zgodne z projektem, przeczytaj Guidelines for Defining and Using Recursive Common Table Expressions

Następujące elementy są niedozwolone w CTE_query_definition z rekurencyjnego użytkownika:

  • select distinct
  • GROUP BY
  • BIORĄC
  • agregacja Skalar
  • TOP
  • lewo, prawo, OUTER JOIN (INNER JOIN jest to dozwolone)
  • Podzapytania

Zauważ, że jeśli zapytanie skręcić w lewo dołączyć do niego self poprzez CTE może stać się nieskończoną rekurencją.

+8

Nie sądzę, że ta odpowiedź lub link rzeczywiście odpowiada "dlaczego". Chciałem połączyć dwa lewe łączenia (do zewnętrznych stołów), aby na przykład kontrolować kierunek następnej iteracji. Nieskończona rekurencja nie wydaje się być dobrym powodem, aby porzucić wszystkie pętle. – crokusek

+3

@crokusek, przygotuj zapytanie koalescencyjne w poprzednim wyrażeniu cte i wewnętrznie połącz je z rekurencyjnym zapytaniem cte. – danihp

+0

Ha, spróbowałem i działa, schludna sztuczka. Jeśli zrobiłem to dobrze, musiałem przekształcić lewe sprzężenia na pełne zewnętrzne w cte. To działało, ale plan zapytania staje się nieszczęśliwy - oblicza pełną zewnętrzną całość przed rozpoczęciem rte (nie zakończyłby się, zależnie od rozmiarów), tracąc w ten sposób rekurencyjnie sondowanie tylko dokładnie tego, czego potrzebował. Kursor zakończyłby działanie, chyba że wynik cte jest mały. Prawdopodobnie jest to miłe obejście niektórych przypadków. – crokusek

8

Nie można używać LEWEGO POŁĄCZENIA z rekurencyjnym CTE, ale można użyć ZAKRESU ZEWNĘTRZNEGO, które powinno dawać takie same wyniki.

Powiązane problemy