2016-05-20 18 views
1

<と同様のファイルとフォルダ構造をモデル化するテーブルを含むSQL Server 2008 R2データベースの商用アプリケーションがあります。<サブレベル1 >:< sublevel 2> .. < sublevel n>:<ドキュメント>。データベーステーブルには値のペア(folder_item、parent)が含まれています。ここで、folder-itemはドキュメントまたはフォルダで、parentはテーブル内の別の行へのリンクです。データ構造が最適でないSQL Serverの再帰的階層型クエリ

は、私は、行ごとに2つの値を返すクエリを記述しようとしています:

  • 文書
  • 文書の直接のコンテナに最上位フォルダから文書への完全連結パス、たとえば、ルート:レベル1:レベル2 ..:レベルN。

通常、再帰的クエリはこの状況を処理できるはずですが、複雑さがあります。 Folder Itemテーブルには、各ドキュメントとサブレベルの冗長エントリが含まれており、それらの直上の親だけでなく、フォルダ構造内のすべての祖先とペアリングされます。

代わりの (文書、親) (親、祖父母) (祖父母、偉大-祖父母) ... (祖先、根)

表は (文書、親)が含まれてい (文書、祖父母) ... (文書、祖先) (ドキュメントルート) (親、祖父母) ... (親、祖先) (親、根) ... (祖父母、おじいさん) ... (祖父母、ルート)

などです。私はデータモデラーが設計の理由を持っていたと確信していますが、標準的な再帰的な階層的なクエリの使用を否定します。実際、試してみると、実行は最大再帰レベル数を超えました。

誰もが同様の問題を抱えていますが、標準のSQL機能を超えた複雑なプログラミングに頼らなくても解決できますか?

おかげで多くの

パトリックあなたが持っていれば

+0

テーブル構造とサンプルデータを投稿するのはどうですか?あなたが単純にその名の上にあなたの再帰を基盤としているなら、あなたは敗北の戦いと戦う可能性が高いでしょう。 –

+0

再帰は、一意ですが非PK VARCHAR値 "DOCNUMBER"に基づいています。ここで、PARENT列には祖先行のDOCNUMBERが含まれています。 –

+0

幸運なことに、既存のフォルダ階層を無視することが決定され、(賢明な)ビジネス上の決定のために問題が消滅したことが判明しました。答えるためにショーンとタブのおかげで.. –

答えて

0

(文書、親)(ドキュメント、祖父母)...(文書、祖先) (ドキュメント、ルートを)(親、祖父母)...(親、祖先)(親、根)...(祖父母、曾祖父母)...(祖父母、根)

あなただけにあなたの再帰を制限したい:

(文書、親)(親、祖父母)(祖父母、偉大-祖父母)(偉大-祖父母、ルート)

右か?したがって、トリックは、現在の行のすべての相対値が現在の行に結合されないように、再帰的cteの下半分に置く条件を特定するだけです。

documentの場合、parentが必要です。 parentについては、grandparentなどが必要です。このフィルタはどのように作成できますか?

まあdocumentについてparentについては、他の祖先については真実ではありません。

回答:documentにはparentと同じ親戚がありますが、唯一documentは祖先としてparentです。

したがって、各folder_itemの親を見ると、その親の親が現在のアイテムの親のものと同じである別の行が存在する場合、そのfolder_itemは現在のfolder_itemの直接の親ではありません。再帰結合から除外されます。

インタビュー:「あなたは私の先祖の一人です。私の他の祖先もあなたを祖先として抱えていない場合、あなたは私の直系親でなければなりません。

true、non?

私がテストするためにあなたの構造を持っていないが、私はあなたの再帰的にこのような何かを追加すること想像してる仕事と参加が、それはいくつかの調整を必要とするかもしれない...このスニペットのために

{for recursion -- Join second half of UNION back to main CTE} 
ON bottom.Folder_Item=cte.parent --you are my ancestor 
AND NOT EXISTS(
SELECT * FROM MyTable mt --others 
WHERE mt.folder_item<>bottom.folder_item --the other is not you 
AND mt.Folder_Item=cte.parent --the other is also my ancestor 
AND mt.Parent=bottom.folder_item --the other also has you as ancestor 
) 

bottomあなたの再帰的なUNIONの下半分の私のエイリアスであり、cteはCTE全体のエイリアスです。

そして、このフィルタを再帰のためのJOIN条件に入れることによって、再帰ツリーが狂って再帰制限を超えないようにする必要があると思います。 I だと思います!

再帰制限を引き続き取得する場合は、再帰CTEの前にCTEでこのようにテーブルをプリフィルタリングしてください。再帰を実行する前に、すべての非即時祖先を事前に削除してください。

これは機能するはずですが、そうでない場合は、必要なものを間違いなくCURSORで行うことができます。

関連する問題