2016-09-27 3 views
0

私は、PHP/MySQLのクロージャーテーブルを使って、Codeigniterを使用しています。私が開発しているアプリケーションでは、領域があり、各領域には場所、部署などPHP/MySQLでクロージャーテーブルに挿入する

私はhttp://www.slideshare.net/billkarwin/models-for-hierarchical-dataを使ってどのように動作するかを知っています。

また、私はデータにアクセスするのに役立つためにhttps://gist.github.com/dazld/2174233を使用しています。私はそれを行うことができます。データを必要に応じて取り出す方法を変更しました。

今はデータを挿入しようとしていますが、私はその周りに頭を浮かべることができません。だから私は、上記のスクリプトからのaddメソッドを適応してきましたが、私はそれを理解していない、と私はそれがエリアテーブル相続人

+------------+-------------+------+-----+---------+----------------+ 
| Field  | Type  | Null | Key | Default | Extra   | 
+------------+-------------+------+-----+---------+----------------+ 
| area_id | int(11)  | NO | PRI | NULL | auto_increment | 
| area_title | varchar(40) | NO |  | NULL |    | 
| area_name | varchar(40) | NO |  | NULL |    | 
| org_id  | int(11)  | NO |  | NULL |    | 
+------------+-------------+------+-----+---------+----------------+ 

に相続人

area_hierarchyテーブルを動作させることはできません

+------------+---------+------+-----+---------+----------------+ 
| Field  | Type | Null | Key | Default | Extra   | 
+------------+---------+------+-----+---------+----------------+ 
| id   | int(11) | NO | PRI | NULL | auto_increment | 
| ancestor | int(11) | NO |  | NULL |    | 
| descendant | int(11) | NO |  | NULL |    | 
| lvl  | int(11) | NO |  | NULL |    | 
+------------+---------+------+-----+---------+----------------+ 

相続人は私がエントリを追加するために使用しようとしている方法:

public function add($node_id, $target_id) { 

    $sql = 'SELECT ancestor, '.$node_id.', lvl+1 
      FROM area_hierarchy 
      WHERE descendant = '.$target_id.' 
      UNION 
      SELECT '.$node_id.','.$node_id.',0'; 

    $query = 'INSERT INTO area_hierarchy (ancestor, descendant,lvl) ('.$sql.')'; 

    $result = $this->db->query($query); 

    return $result; 

} 

ので具体的には、$は何ですかnode_id、および$ target_id。

lvl + 1とは何ですか?

新しいトップレベル領域を追加すると、このデータはどのようなデータに渡されますか?

クエリも失敗したとareaテーブルからarea_id列の値になりますUNION

+1

ノードIDは追加する新しいノード(子)で、ターゲットIDは親(祖先)ノードです。組合は自己参照に対処することです。自己参照は常に閉じておくべきです。 BをDの下に追加したい場合は、Bのすべての祖先を選択してDとの関係を作成する必要があります。また、D = Dの場合、結合の自己参照を作成する必要があります。 –

+1

あなたの例では、10個のエリア1,2,3,4,5があり、それらが全く同じ主キーを持っているとします。それらはすべてルートレベルに存在する必要があります。最初にそれらの領域を追加してから、各ノードに 'add($ areaId)'を呼び出します。次に、6,7,8を3の子にします。次に、それぞれの領域に対して 'add($ areaId、3)'を呼び出します。最後に、9と10を8の子にします。add($ areaId、8)を呼び出します。あなたの質問がなぜ失敗したのか、あるいは期待どおりに機能しないのかについて助けが必要な場合は、私たちにエラーと期待される結果を与える必要があります。 –

+0

ありがとう、良い説明。私は離れて、experiement – frobak

答えて

1

$node_id後の構文エラーを示します。おそらく、それはあなたがちょうどエリアテーブルに追加した行です。

$target_idareaテーブル内の別の行からarea_idカラム、あなたが「親」、直接の祖先として同定されている行の値であろう。

lvl+1は、階層内の世代またはレベルです。子孫がその親からどのように遠く離れているか。

新しい「トップレベル」領域を追加する場合は、$target_idには$node_idを使用します。

これを理解する最も良い方法の1つは、area_hierarchyテーブルの「現在の状態」と、ノードが追加されたときのテーブルの「終了状態」を調べることです。ツリーの中だけでトップレベルのノードとの

、= 11をAREA_ID、area_hierarchy表は次のようになります。

ancestor descendant lvl 
-------- ---------- --- 
11  11   0 

私たちは地域のテーブルに別の行を追加する場合、= 22 AREA_ID、子としてAREA_ID = 11の(直接子孫)、我々はarea_hierarchyに、これらの2つの行を追加する必要があります

ancestor descendant lvl 
-------- ---------- --- 
11  22   1 
22  22   0 

我々はAREA_ID = 22の子として、= 333 AREA_ID、エリアテーブルに別の行を追加した場合、我々は必要これらの行をarea_hierarchyテーブルに追加します。

ancestor descendant lvl 
-------- ---------- --- 
11  333  2 
22  333  1 
333  333  0 

追加する必要がある最初の2行は、テーブルに既に存在する行のように見えます(descendant = 22)。違いは、新しい行の子孫は22ではなく333であり、lvlの値はすでにテーブル内にあった行よりも1つ多いということです。

私たちが追加する必要があるのは、それ自身への参照です。ちょうど私たちがarea_id = 11をそれ自体の「親」として持っていたように。

UNIONの後の部分から3番目の行です。すでにarea_hierarchyにある行をコピーして、子孫列の値を追加するノードのID(333)に置き換え、lvlを1だけ増やして最初の2行を取得します。

どの行追加する必要があり、テーブル内の他の行をコピー/変更することによってそれらを派生させる方法があれば、SQLは意味を持ち始めます。


あなたは、AREA_ID = 333のために、これら3つの行を追加するadd関数を呼び出す達成します:あなたは、階層内の新しい "トップレベル" としてAREA_ID = 4444を追加したい場合は

add(333,22); 

add(4444,4444); 
+0

ありがとうございました。非常に有益であり、明確にしています。今私はもう1つの質問があります。私はクロージャーテーブルを列で索引付けすれば、組織のIDと言うことができますか? – frobak

+0

@frobak:はい、適切なインデックスを追加してください。インデックスは、いくつかの重要な目的を果たします。 1つは、索引を使用して固有の制約を実施することができます。データベースに重複行がテーブルに追加されないようにするには、一意制約を追加します。たとえば、2番目の呼び出し 'add(4444,4444)'を実行することを考えてみましょう。あなたはどのような最終状態をデータベースに入れたいですか? area_hierarchyテーブルに2つの同じ*行が必要ですか?索引のもう1つの目的は、パフォーマンスを向上させることです。どの索引が最も適しているかは、文が実行される文によって異なります。 – spencer7593

関連する問題