問題タブ [transitive-closure-table]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
mysql - ノードが繰り返されるクロージャテーブル内のMySqlソート階層データ
Bill Karwinで説明されているように、クロージャ テーブルとして表した階層があります。深さ優先トラバーサルとしてソートされたノードを返すクエリを作成しようとしています。この返信は私の問題を解決しますが、私の構造では、複数の親を持つためにいくつかのノードが複数回表示されることを除きます。
サンプルデータは次のようになります。
- 1
- 2
- 5
- 3
- 5
- 4
- 6
- 2
- 5
- 2
ご覧のとおり、ノード 2 は、ルートの子と孫の両方として 2 回表示されます。ノード 5 は、ルートの孫として 2 回表示され (毎回異なる親を持つ)、その親であるノード 2 が繰り返されるため、再びひ孫として表示されます。
これにより、データがクロージャ テーブルとして設定されます。
または隣接リストとして:
幅優先トラバーサルを生成できます (ただし、5 は孫として 1 回しか表示されません)。
しかし、ブレッドクラムを使用した深さ優先トラバーサルの試みは失敗します ( GROUP BY a.descendant
.
クロージャテーブル表現を使用して深さ優先トラバーサルを出力することは可能ですか?
別の表現を使用する必要がありますか? 私は MySql に制限されているため (再帰 CTE を実装していません)、再帰 CTE を使用できません。
postgresql - 再帰クエリを使用して階層ツリー構造を逆方向にトラバースする方法
私は PostgreSQL 9.1 を使用して、ノードへの接続を持つエッジ (または要素) で構成される階層ツリー構造のデータをクエリしています。データは実際にはストリーム ネットワーク用ですが、問題を単純なデータ型に抽象化しました。例のtree
テーブルを考えてみましょう。各エッジには長さと面積の属性があり、ネットワークからいくつかの有用なメトリックを決定するために使用されます。
これは、AE で表されるエッジがノード 1 ~ 5 に接続されている以下に示すことができます。NULL to_node
(Ø) は終了ノードを表します。はfrom_node
常に一意であるため、PK として機能できます。このネットワークが流域のように流れる場合、支流の開始エッジは A、B、C であり、流出エッジの終了は E です。
のドキュメントはWITH
、再帰クエリで検索グラフを使用する方法の良い例を提供します。したがって、「前方」情報を取得するために、クエリは最後から開始され、逆方向に動作します。
上記は理にかなっており、大規模なネットワークに適しています。たとえば、エッジB
は端から 3 エッジであり、前進パスは{B,D,E}
先端から端までの全長が 3.5 であることがわかります。
ただし、逆クエリを作成する良い方法がわかりません。つまり、各エッジから、蓄積された「上流」のエッジ、長さ、および面積はいくらかです。を使用してWITH RECURSIVE
、私が持っている最高のものは次のとおりです。
各ダウンストリーム エッジは 1 つまたは多数のアップストリーム エッジに接続するため、再帰クエリの 2 番目の項に集計を組み込みたいと考えていますが、再帰クエリでは集計が許可されていません。また、with recursive
結果には の結合条件が複数あるため、結合がずさんであることは承知していedge
ます。
逆/後方クエリの予想される結果は次のとおりです。
この更新クエリを作成するにはどうすればよいですか?
最終的には、正確な長さと面積の合計を蓄積することに関心があり、パス属性はデバッグ用であることに注意してください。私の現実のケースでは、順方向のパスは最大で数百であり、大規模で複雑な集水域の逆方向のパスは数万になると予想しています。
mysql - これらの SQL クロージャ テーブルの例の違いは何ですか?
SQL クロージャ テーブルに頭を悩ませているので、見つけたいくつかの例を理解するための助けが必要です。
sample_items
次の階層データで呼び出されるテーブルがあるとします。
ツリー構造は事実上次のようになります。
ツリーのクエリ (特定の ID のすべての子孫を検索するなど) を容易にするために、この優れた SO 投稿 で Bill Karwin によって説明されている方法sample_items_closure
を使用して呼び出されるテーブルがあります。また、必要に応じて直接の子または親を照会するためのオプションの列も使用します。この方法を正しく理解していれば、クロージャー テーブルのデータは次のようになります。path_length
のすべての行には、それ自体とそのすべての先祖の両方sample_items
のエントリがテーブルに含まれています。sample_items_closure
これまでのところ、すべてが理にかなっています。
ただし、他のクロージャー テーブルの例を調べているときに、ルート レベル (ancestor_id 0) にリンクし、パスの長さが 0 である行ごとに追加の祖先を追加するものに出くわしました。上記と同じデータを使用すると、次のようになります。クロージャーテーブルは次のようになります。
より良いコンテキストを提供するために、そのサイトで使用されている選択クエリを、私の例に合うように変更したものを次に示します。
この方法に関連する 2 つの質問があります。
質問1:
各子孫をルート レベル (id 0) にリンクする追加の行が追加されるのはなぜですか?
質問2:
前の祖先の path_length + 1 ではなく、これらのエントリの path_length が 0 になるのはなぜですか? 例えば:
おまけの質問:ツリーの完全な構造が既にクロージャ テーブルで表現されているのに、一部の例にまだ隣接リスト (私の例では のparent_id
列) が含まれているのはなぜですか?sample_items
mysql - MySQL で推移閉包サブツリーを移動する
SQL Antipatterns に記載されているレシピに基づいて、現在 MySQL を使用して隣接リストを使用しているシステムに推移閉包テーブルを改造しようとしています。ただし、サブツリーの移動の実装で問題が発生しました。
開発作業のために、既存のシステムとクロージャ テーブルを極端に単純化したものを作成しました。満足のいく方法で動作するようになったら、これを実際のデータに移植します。私のテーブルは次のとおりです。
私のテストデータは次のとおりです。
製品テーブルの行作成時に閉鎖テーブルに行を挿入し、製品行が削除されたときに閉鎖テーブルから行を削除するトリガーを実装しましたが、それらは正常に動作しますが、MySQL の制限により、更新のケースを取得できません (製品テーブルの親が変更されます) が機能します。
ノード 1 ではなくノード 2 の子になるようにノード 4 を更新したい場合。
SQL アンチパターンの本では、これを行うためのクエリが提供されています。最初のものは、関連する行をクロージャ テーブルから削除することによって、既存のサブツリーを孤立させることを目的としています。
しかしもちろん、MySQL では、サブクエリで使用しているテーブルを変更できない設計上の欠陥があるため、これを行うことはできません。
そこから行を削除できるため、クエリを自己結合に書き直そうとしています。元のクエリを削除ではなく選択するように変更しました。これは機能するためです。比較のベースラインとして使用できます。ただし、結合を使用してクエリを複製しようとすると、空のセットが返されます。
トリガーに入れる必要があるため、実行されるクエリを比較的単純に保つ必要があります。また、ライブ SQL サーバーがクラスターで実行されているため、一時テーブルも使用できません。一時テーブルを使用するとレプリケーションが壊れるという問題が過去にありました。MySQL で行を削除できるように、クエリをフォームに書き直すのを手伝ってくれる人がいれば、ありがたいです。
postgresql - ストリーム ネットワークの有向グラフで Strahler 数を決定する方法
質問・例・期待値
ストリーム ネットワークを表す有向グラフのStrahler 数またはStrahler ストリーム次数を決定する必要があります。クエリを使用して前方および後方にWITH RECURSIVE
情報を取得できますが、ストラーラー数を決定するには別のことを行う必要があるようです。
たとえば、ここに 10 の支流と 1 つの流出口を持つ 19 セグメントのストリーム ネットワークがあります。各セグメントの上流部分は、ノード ID で表されます。
そして、セグメントが によって接続されているテーブル構造の同じデータto_node
。これは流域の排水口では null です。
Strahler 数の期待される結果 ( expected_order
) は、次のように視覚化されます。
3 つのルールがあります ( GRASS 7.0 マニュアルから):
- ノードに子がない場合、ストラー次数は 1 です。
- ノードにストラーラー最大次数iの支流が 1 つだけあり、他のすべての支流の次数が i より小さい場合、次数はiのままです。
- ノードに最大次数iの支流が 2 つ以上ある場合、ノードのストラー次数はi + 1 です。
私が見つけた/試したこと
この問題を解決するために掘り下げて発見したことから、この計算はSQLで実行できるということです(ただし、「SQLスクリプト」はMS SQL Server用に書かれていると思います)。しかし、PostgreSQL 9.1 でできることは見つかりませんでした。
私が行った最善の試みの 1 つは、各ノードから上流ノードの数を数えることです。これにより、支流 (1 次) が正しく識別されますが、他のノードは識別されません。
アイデアは、適切に設定されたウィンドウ フレーム範囲でnth_value(value any, nth integer)
ウィンドウ関数を使用することです。ただし、これを設定する方法、または Strahler 番号を識別するように設定できるかどうかはわかりません。もう 1 つの [あまり面白くない] アイデアは、Strahler 数ごとに反復を手動で実行することです。これは、実世界のデータに対して 5 ~ 8 次 (反復) であると予想されます。これはステートメントで実行できます。しかし、より良いアイデアは大歓迎です。DO
symfony - Doctrine 2 ツリー拡張: クロージャーテーブル
Doctrine 2 と Closure Table Strategy の Tree - Nestedset 動作拡張を使用しています。私の Web では、ユーザーはフォルダーとサブフォルダーを作成して表示できます。Closure Table 戦略を使用してこれを実装し、childrenHierarchy()メソッドでフォルダーをレンダリングします。
正常に動作しますが、すべてのユーザーのすべてのフォルダーを返します。この場合、 user_idを定義して、ログイン ユーザーに属するフォルダーのみをレンダリングする方法がわかりません。これを行う方法はありますか?
私はあなたの答えを嬉しく思います。
c# - 親子関係に基づいてレコードを返す方法
特定のポジションの親部門を選択する必要があるという要件があります。私はテーブルを持っています
ここで、ポジションは別のポジションまたは部門として親を持つことができます。Pos1 が Pos2 として親を持ち、Pos2 が Pos3 として親を持ち、Pos3 が Dept1 として親を持つとします。では、他の位置を介して Pos1 の親である Dept1 を取得するにはどうすればよいでしょうか。ここで、Dept1 が Pos1 の直接の親である場合、それを見つけて修正することができますが、ポジションが deparment に間接的に親を持っている場合のクエリの書き方です。
すべての返信に感謝します。ここで、Pos3 の親部門を取得するかどうかを指定します。それから私は簡単に言うだろう
これで、その位置の親部門が表示されます。Pos1 には直接の親としての部門がないため、次のように言います。
お役に立てれば。
php - クロージャテーブルモデルを使用した Doctrine2 による階層データ
クロージャ テーブル モデルを使用して保存された既存のデータがいくつかあります。私はDoctrineを初めて使用し、この「Doctrineの方法」でエンティティを実装しようとしていますが、どうすればよいかわかりません。私が従おうとしている哲学は、エンティティは単純な古い PHP オブジェクトであるべきであり、親子の関連付けを構成するために何らかの注釈を使用する必要があるということです。
この投稿では、Category をエンティティの例として使用します。エンティティが次のように見えると私が想像するものは次のとおりです。
閉鎖テーブルは次のようになります。
このテーブルは基本的には結合テーブルです。親子関係のみが格納されるため、多対多の関係を作成するときにエンティティが存在しないのと同様に、ここにエンティティが存在しても意味がないと思います。と@JoinTable
。
他のエンティティと同じようにカテゴリ エンティティを使用できるようにしたいと考えています。リポジトリから取得したときに$parent
/が入力され、呼び出されたときに SQL が実行され、新しく追加された子が反映されます。$children
$em->flush()
ここで使用される SQL の例:
新しい子を追加します。
サブツリーを新しい親に移動します。
カテゴリのすべての子を取得します。
ここでいくつか質問があります。まず第一に、これは合理的なアプローチ/Doctrineで実装できるもののように見えますか? そうでない場合、これにアプローチするより良い方法はありますか?
これが合理的なアプローチのように思える場合、これを攻撃する方法を考えていますか? これらのファイルを配置する必要がある場所/クラスを設定する方法と、実際の実装を提供してくれる人をもっと探しています。始めるのに役立つドキュメントや例は大歓迎です。私は Doctrine の経験がほとんどありません。
ms-access - Access データ マクロから SQL クエリを実行する
データ マクロを使用してクロージャ テーブルを更新しようとしています。これには、新しいレコードがメイン テーブルに挿入されるたびに次のコードを実行する必要があります。
ご覧のとおり、ネストされたループを使用してこの操作を実行できます。
メイン テーブル (tblNodes) とクロージャ テーブル (tblClosure) の両方がバックエンド データベースに格納されているため、データ マクロで必要なことを実行できるはずです。
データ マクロには、関数Create Record (in...)およびFor Each Record (in...)もあるようです。しかし、私はその2番目のものをまったく発火させることができません。
これは私のコードです(パラメータとしてtemp_node
andを定義しました):temp_parent