5

ルート項目を選択したいのですが、それは可能な限りパフォーマンスの高い子です。私はネストされたセット モデルを使用することを好みますが、今回のテーブル構造は隣接モデルに従っています。ネストされたセットと隣接モデルの詳細

私は と を持ってdependencies-tableitems-tableます。

依存関係テーブル

dependency_id | item_id | child_id 
            1 |       1 |        4
            2 |       2 |        5
            3 |       4 |        7
            4 |       7 |        3
            5 |       9 |        3
            6 |       1 |        2

品目表

item_id | name   | info
      1 | Item A | 1st Item
      2 | Item D | 2nd Item
      3 | Item C | 3rd Item
      4 | Item D | 4th Item
      5 | Item E | 5th Item
      6 | Item F | 6th Item

SQL、最初に試す

# selecting children (non-recursive)
# result: 4, 2
SELECT 
   child_id AS id 
  FROM `dependencies_table`
 WHERE item_id = 1

この SELECT 再帰が必要です。

望ましい出力

# children of item #1
dependency_id | item_id | child_id
            1 |       1 |        4 // 1st level
            6 |       1 |        2 // 1st level
            2 |       2 |        5 // 2nd level, 1->2->5

このケースは非常に一般的なはずですが、今のところベストプラクティスを見つけることができなかったのではないかと思っています. 注意: これは MySQL であるため、CTE を使用できません

この問題をどのように解決しますか?前もって感謝します!

編集:興味深いスレッドを見つけましたが、私の問題はまだ解決されていません。したがって、この質問を閉じないでください。

編集 2: これは興味深い PHP ソリューションですが、残念ながら私が実際に望んでいるものではありません。

4

2 に答える 2

2

NoSQL 担当者として、それがグラフの目的であると言わざるを得ません。しかし、ええ、わかりました..SQLを使用する理由がありますが、この特定の例は、これらのデータベースが作成されたものではありません。特に、nレベルの子を持つことができる場合、mysqlの実行は非常に遅くなります。実際にはクエリがありますこのため、n レベルでも、それはクレイジーなたわごとです。(私の記憶が正しければ、約 42 個の内部結合)

ええ、あなたはテーブルをフェッチして、php で子を処理したいと考えています。

依存関係テーブル全体を取得したら、php で結果を取得する方法を次に示します。

$dep = array();
$dep[] = array('item_id' =>'1', 'child_id' =>'4');
$dep[] = array('item_id' =>'2', 'child_id' =>'5');
$dep[] = array('item_id' =>'4', 'child_id' =>'7');
$dep[] = array('item_id' =>'7', 'child_id' =>'3');
$dep[] = array('item_id' =>'9', 'child_id' =>'3');
$dep[] = array('item_id' =>'1', 'child_id' =>'2');

function getchilds($dependencies, $id) {

    $ref = array();
    foreach($dependencies as $dep){
        $item_id = $dep['item_id'];
        $child = $dep['child_id'];
        if(!is_array($ref[$item_id])) $ref[$item_id] = array('id' => $item_id);
        if(!is_array($ref[$child])) $ref[$child] = array('id' => $child);
        $ref[$item_id]['children'][] = &$ref[$child];
    }
    return $ref[$id];
}

getchilds($dep,1);

これは、参照を使用してすべてのアイテムを一度だけ通過します。これ以上のパフォーマンスをイメージすることはできず、無限の数のレベルで機能します。実際、これは一定数のレベルの SQL クエリよりも高速であるに違いありません。

最初のアイテムの場合、これは基本的にあなたに与えます

1 - 2 - 5
 \ 
  4 - 7 - 3
于 2013-09-21T20:16:24.983 に答える