2017-12-27 38 views
2

私はアンカーが必要であることを知っています。そして、再帰的なCTEがない場合、UNION ALLが必要であることがわかります。ただ動作しません...しかし、なぜそういうのかの良い説明は見つかりません。すべてのドキュメントには、必要なことだけが記載されています。なぜTransact-SQLの再帰CTEにUNION ALLではなくUNIONが必要ですか?

はない我々は再帰クエリで UNIONの代わり UNION ALLを使用することができますなぜ

?より深い再帰に重複を含まないのは良い考えですね。そのようなものは、すでにすでにフードの下で働いているはずです、私は思うでしょう。

+0

私はあなたが意味するものが得られないので、いくつかのコードをご覧ください。 – Sami

+0

コメントしますか? –

+0

@Sami再帰的なCTEの定義では、再帰的なクエリにアンカークエリ 'UNION ALL'を必要とします。私はUNIONではなくUNION ALLにする必要があるのか​​と尋ねています。これは、オプティマイザがおそらく何らかの形でやっていると思います。 –

答えて

2

私は、これを実装する価値があるとは考えていないと考えています。 Postgres does support bothUNIONUNION ALLのように見えます。

この機能を使用する場合は、Connect(またはその置き換え先のURL)にフィードバックを送信できます。

重複を追加するのを防ぐことは、後のステップで前のステップに追加された重複行がほとんどいつも無限ループを引き起こしたり、最大再帰制限を超えてしまうために役立ちます。

コードは、このような

enter image description here

以下のようにUNIONを実証使用されているSQL Standardsでかなりの数の場所があります。この記事では、どのようにthey are implemented in SQL Serverを説明します。彼らはそのようなことをしていません。スタックスプールは行を削除するので、後の行が削除された行の複製であるかどうかを知ることはできません。 UNIONをサポートするには、やや異なるアプローチが必要です。

これまでのところ、マルチステートメントのTVFで同じことを達成するのは簡単です。UNION ALLUNIONを変更し、最後にDISTINCTは無限再帰からあなたを保存されません追加する(Postgres Fiddle

WITH R 
    AS (SELECT 0 AS N 
     UNION 
     SELECT (N + 1)%10 
     FROM R) 
SELECT N 
FROM R 

下の愚かな例を取るために

しかし、あなたは上記の重複を破棄するIGNORE_DUP_KEYを使用しています

CREATE FUNCTION dbo.F() 
RETURNS @R TABLE(n INT PRIMARY KEY WITH (IGNORE_DUP_KEY = ON)) 
AS 
    BEGIN 
     INSERT INTO @R 
     VALUES  (0); --anchor 

     WHILE @@ROWCOUNT > 0 
     BEGIN 
      INSERT INTO @R 
      SELECT (N + 1)%10 
      FROM @R 
     END 

     RETURN 
    END 

GO 

SELECT * 
FROM dbo.F() 

としてこれを実装することができます。列リストの幅が広すぎて索引付けができない場合は、代わりにDISTINCTNOT EXISTSが必要です。おそらく、再帰の最大回数を設定し、無限ループを回避するパラメータが必要になるでしょう。

+0

...それは基本的にSQL Serverの技術的な制限です。面白い! –

+1

補足として、私は実際にはUNIONを使用する必要はありませんが、それはちょうど長い間反直観的であると私に打たれました。そして、昨日私は最終的に誰もそれを議論するように思われなかった。 –

2

これは純粋な推測ですが、各繰り返しの結果を個別に計算できることをUN​​ION ALLが保証していると思います。本質的には、反復が別の反復を妨げることはありません。

UNIONはバックグラウンドでソート操作を必要とするため、以前の反復の結果が変更される可能性があります。プログラムは、呼び出しスタック内の前の呼び出しの状態を変更するべきではありません。入力パラメータと後続の反復の結果を使用して呼び出し関数と対話する必要があります。これは、おそらくSQL Serverの再帰的なCTEに基づいて操作を設定するために適用する必要があります。

私は間違っているかもしれない、深夜の脳ダンプは100%の信頼性ではありません:)

編集(ちょうど別の考え):

再帰が起動したら、あなたはコールスタックを持っています。このスタックの各レベルは結果の計算を開始しますが、後続のすべての呼び出しの結果が完了してその結果を返す前に待機する必要があります。 UNIONは重複を排除しようとしますが、終了条件に達するまで(そして最後は下から上に構築されます)、レコードはありませんが、後続の呼び出しの結果は上のものによって要求されます。 UNIONは最後にDISTINCTに縮小されます。

+0

呼び出しごとにスタックに追加される再帰呼び出しはどれもありません。それが事実だったなら、それが進行するにつれてそれがなくなると私には思われます。 –

+0

これが最高のソリューションパフォーマンスを発揮するかどうかはわかりません。つまり、ソートと比較は各反復後に行わなければなりません。私は、最終結果を計算した後にそれを行うことは、多くの場合(確かにすべてではない)、より合理的であると言います。編集中の呼び出しスタックは、プロシージャ再帰の仕方から導かれます。SQL Serverではオプティマイザと言えば間違っているかもしれません。 – Pred

+0

最後に行うのは同じではありません。終端処理と無限ループとの違いを生み出すことができます。 –

関連する問題