2012-02-03 31 views
10

はちょうど再帰的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 

の下に子与えられ、それがルートレベルの親を返すということです....プログラムは完全に罰金、すべての時間を働いている考えてみましょう好奇心/実験的な酒の私は、左外部結合に登録しよ変更し、それがメッセージ462、レベル16、状態1、プロシージャGetParent関数、9行 外部結合は、再帰共通テーブルの再帰部分では許可されていません

を報告しました式 'GetParentOfChild'。

CTEの再帰的な部分がLeft Outer Joinを受け入れられないのはなぜですか?それは設計によるのですか?

おかげで

答えて

6

はい、それは仕様です、以下の項目が 再帰メンバーのCTE_query_definitionに許さされていないGuidelines for Defining and Using Recursive Common Table Expressions

をお読みください。

  • DISTINCT
  • を選択
  • グループ
  • LEFT、RIGHT、外部結合(INNER JOINのが許可されている)
  • スカラ集約をHAVING
  • TOP
  • サブクエリ

あなたのクエリは左を作る場合は、それに参加することに注意してくださいセルフスルーCTEは無限再帰になります。

+8

私はこの回答やリンクが実際に「なぜ」と答えるとは思わないのですか?私は、次の反復の方向を制御するために、2つの左結合(外部表への結合)を結合したいと考えました。無限の再帰は、すべてのwhileループを放棄する正当な理由のようには見えません。 – crokusek

+3

@crokusekを使用して、以前のcte expresionで結合クエリを作成し、それを再帰的cteクエリに内部結合します。 – danihp

+0

ハ、私はそれを試して、それは、きちんとしたトリックを実行します。もし私がそれを正しくしたら、左の結合をcteの完全な外側に変換しなければならなかった。それは実行されましたが、クエリプランは悲惨なものになります。rteを開始する前に完全な外側を完全に計算します(サイズに応じて終了しません)。必要なものだけを再帰的に探索します。 cte結果が小さい場合を除いて、カーソルは実行されません。それにもかかわらず、場合によってはおそらく素晴らしい回避策です。 – crokusek

8

LEFT JOINは再帰CTEでは使用できませんが、OUTER APPLYを使用すると同じ結果が得られます。

関連する問題