3

私は現在、教師がオンラインでカリキュラムを計画できるアプリケーションを書き直しているところです。

このアプリケーションは、教師が生徒の作業単位を作成するプロセスをガイドします。現在、このツールは 3 つの州で使用されていますが、それ以上に拡大する計画があります。

このアプリケーションの主な特徴の 1 つは、学生のすべての成果がシステムにプリロードされていることです。これにより、教師は各作業単位で達成される結果を検索または参照して選択することができます。

私が最初にシステムを設計したとき、私はすべての学生の成果が同様の階層に従うと仮定しました。つまり、名前付きのネストされたコンテナとその結果があります。

私が入力した最初の結果セットは 3 層でした。そのため、私のデータベースには次の構造があります。

=========================

太字の表

h1

ID、名前

h2

id、parent___id (h1_id)、名前

h3

id、parent___id (h2_id)、名前

結果

id、parent___id (h3_id)、名前

=========================

n/ レベルの階層を追加できないことは明らかですが、この方法では、データベースに再帰的にクエリを実行せずにすべての標準のリストを表示することも困難でした。

学生の成果 (およびその親カテゴリ) が追加されると、それらを変更する理由はほとんどありません。主な要件は、読みやすく効率的であることです。

これまでのところ、さまざまな学校/州/国からの生徒の成績はすべて、私の仮定にほぼ従っています。これは常に当てはまるとは限りません。

もちろん、既存のデータはすべて現在のデータベースから転送する必要があります。

上記を考慮して、さまざまな学生の成果セットをすべて保存するための最良の方法は何ですか? 私が持っていたアイデアのいくつかを以下にリストします。

  • 再帰または多数の結合を使用する場合は、データベース内の 4 つのテーブルを引き続き使用します。

  • ネストされたセットを使用する

  • XML (すべての異なるセットのグローバル XML ファイル、またはそれぞれの XML ファイルのいずれか)

4

3 に答える 3

6

これには実際に4つのテーブルが必要かどうかはわかりません。

parent_id とレベルを追跡する単一のテーブルがある場合、無限のレベルを持つことができます。

結果

id、parent_id、レベル、名前

再帰を使用して、特定の要素のツリーを追跡できます (実際にはレベルは必要ありませんが、レベルを使用するとクエリが簡単になります)。

代替手段はネストされたセットです。この場合でも、単一のテーブルにマージしますが、set スタッフを使用してレベルを追跡します。

どちらを使用するかは、アプリケーションによって異なります。

読み取り集中: ネストされたセット

書き込み集中型: 親ツリーのようなもの

これは、ネストされたセットを使用すると、単一のクエリでツリー全体を取得できますが、新しいノードを挿入するたびにツリー全体を並べ替えるというコストがかかるためです。

parent_id を追跡するだけで、ノードを個別に移動または削除できます。

PS: 私は XML に反対票を投じます。同じ再帰的な問題に加えて、データを解析するオーバーヘッドと、データをデータベースまたはファイルシステムに格納するオーバーヘッドがあります (これにより、同時実行の問題が発生します)。

于 2008-12-04T07:17:58.280 に答える
1

私は他のポスターに同意します-ネストされたセットが行くべき道だと思います。

ここを参照してください:

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

それは理論を説明し、それをあなたがすでに使っているものと比較します - これは本当に隣接関係のひねりです. すべての +/- を示しており、プロジェクトのすべての微妙な点に基づいて決定を下すのに役立ちます。

(CakePHP のツリー動作で) 私が見たもう 1 つのことは、実際には両方を同時に使用することです。確かにパフォーマンスに関してはそれほど優れていませんが、このモデルでは、隣接関係の場合と同じように挿入/削除します。次に、ネストされた選択を実行できるように、左/右のエッジ値を再構築するために実行するメソッドがあります。ファッションを設定します。その結果、挿入/削除がはるかに簡単になります。

http://book.cakephp.org/view/91/Tree

于 2008-12-04T08:42:10.950 に答える
0

データベースでツリーを処理する別の方法があります。ネストされたセットやここで説明する他のパターンほど「スマート」ではないかもしれませんが、これは非常に効率的で簡単です。

アイテムのレベル (または深さ) を格納する代わりに、次のようにフル パスをツリーに格納できます。

A
  B
  C
    D
  E

次のように保存されます。

item  |  parent  |  path
----------------------------
A     |  NULL    |  A
B     |  A       |  A--B
C     |  A       |  A--C
D     |  C       |  A--C--D
E     |  A       |  A--E

次に、簡単に取得できます。

  • (純粋な SQL) whereparent = '' 句を持つアイテムのすべての直接の子
  • (純粋な SQL) where path LIKE 'PARENT--%' 句を持つすべての直接および間接の子
  • (PHP) ノードの深さ (count(explode('--',$path))

これらの機能は、適切なインデックス (PK、親のインデックス、パスのインデックス) を作成する限り、ほとんどの状況で十分であり、いくつかのサブレベルがあっても非常にパフォーマンスが高くなります。確かに、このソリューションは、ノードを削除/移動してパスを更新するときに要求が厳しいです...

これが役立つことを願っています!

于 2009-11-04T17:15:13.143 に答える