11

深さに制限はありません。

構造化されたブランチまたはツリー全体を取得するにはどうすればよいですか?

定義はここからです:MySQLでの階層データの管理

4

5 に答える 5

5

それがあなたが求めているものかどうかはわかりませんが、ツリー全体、パスごとに 1 行、各パスを文字列として取得できることに注意してください。http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/からの単一パス」の例

SELECT 
  GROUP_CONCAT(parent.name ORDER BY parent.lft ASC SEPARATOR '|') 
FROM nested_category AS node
     CROSS JOIN nested_category AS parent 
WHERE 
  node.lft BETWEEN parent.lft AND parent.rgt 
GROUP by node.id 
ORDER BY node.lft;

これにより、ツリー内のすべてのノードのパスが出力されます。

nested_category AS node CROSS JOIN nested_category AS parentと同等であることに注意してくださいnested_category AS node, nested_category AS parent

これは、文字列'|'を区切り文字として指定します。これをパス要素の配列に分解したい場合、データにない文字列があることがわかっている場合は、代わりにそれを指定できます。

于 2012-08-31T02:41:52.340 に答える
2

私は同様のアプローチを使用しますが、まったく同じではありません。これは、子の親への参照も保持します。これにより、データからツリー構造を簡単に構築できます。これが役立つ場合は、PHP でデータをツリーに抽出するためのコードを投稿できます。

@Marc、説明されているデータ構造は、必ずしもセット操作を行うためのものではありません。構造の操作が簡単になるだけです。データのツリー全体を取得する必要があり、各レコードに親レコードへのポインターが格納されているだけの場合は、データベースを再帰的にクエリして、データのツリー全体を取得する必要があります。そこで説明されているアプローチを使用すると、1 つのクエリでセット全体を抽出できます。

編集:これは、子を維持する場合にツリー構造を構築するコードです->親参照とlft/rightのもの。ツリーの単一レベルの直接の子孫のみを取得したい場合は、この方法の方が実際には高速であるため、私はこれを行うことを好みます。

本質を示すためにそれを取り除いてみたので、タイプミスなどがあるかもしれませんが、アイデアを得る必要があります. 重要な部分は

  • クエリを "lft ASC" で並べ替えます。このようにすると、常に親ノードが子ノードの前に処理されます。
  • 各ノードへの参照を ID で保存します。このようにして、そのノードの子は簡単に見つけて親に追加できます。
  • 結果を反復処理し、(上記のように) ID ごとにそれぞれの参照を保存し、このノードをその親の子に追加します。

とにかく、ここにコードがあります -

<?php
$children = mysql_query('SELECT * FROM nested_category ORDER BY lft ASC');

/* Get the first child; because the query was ordered by lft ASC, this is
   the "root" of the tree */
$child          = mysql_fetch_object($children);
$root           = new StdClass;
$root->id       = $child->folderID;
$root->children = array();
/* Store a reference to the object by the id, so that children can add
   themselves to it when we come across them */
$objects        = array($root->id => $root);

/* Build a tree structure */
while ($child = mysql_fetch_object($children)) {
    /* Create a new wrapper for the data */
    $obj           = new StdClass;
    $obj->id       = $child->id;
    $obj->children = array();
    /* Append the child to the parent children */
    $parent = $objects[$child->parent];
    $parent->children[] = $obj;
    $objects[$obj->id] = $obj;
}   
于 2010-04-10T15:57:26.123 に答える
0

mysql 側のデータ構造が多少変わっている場合でも、データは通常のクエリ メソッドを使用して取得されます。適切な select ステートメントを発行し、結果をループして、PHP 配列に詰め込みます。MySQL よりも PHP で集合操作を行う方がはるかに難しいため、なぜそうしたいのかはわかりません。

于 2010-04-07T14:20:19.007 に答える
0

php..を使用して再帰を使わずにツリー構造を操作できる方法についてお知らせします。標準 php ライブラリ (SPL) についてはよく知られていると思います。質問にはイテレータを使用できます。

http://www.php.net/~helly/php/ext/spl/

SPL のドキュメントへのリンクは次のとおりです。上記のMysqlリンクの例のいくつかのソリューションを次に示します:-テーブルから配列を取得するだけで、配列を操作して好みに合わせて表示できます

For :- 隣接リスト モデル

すべての子を含むすべての結果を表示する「RecursiveIteratorIterator」を使用できます。

子供だけ見せたいなら。「ParentIterator」を使用できます

于 2010-04-15T05:06:18.597 に答える
0

あなたのリンクを見ると、Left Joinsでそれを行います。完全なツリーの取得の例を見てください。

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4 FROM category AS t1 LEFT JOIN category AS t2 ON t2.parent = t1.category_id LEFT JOIN category AS t3 ON t3.parent = t2.category_id LEFT JOIN category AS t4 ON t4.parent = t3.category_id WHERE t1.name = 'ELECTRONICS';

含める階層レベルごとに LEFT JOIN が必要です。結果は、php によって任意の望ましいデータ構造に解析できます。NULL結果を無視するだけです。

| ELECTRONICS | TELEVISIONS | TUBE | NULL |

| ELECTRONICS | TELEVISIONS | LCD | NULL |

| ELECTRONICS | TELEVISIONS | PLASMA | NULL |

| ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS | FLASH |

| ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS | NULL |

| ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL |

構造が深い場合、多くのテーブルを結合する必要がある場合、MySQL Join の実行に長い時間がかかるため、これは悪い方法です。

あなたの質問を誤解していないことを願っています。

于 2010-04-12T16:31:56.600 に答える