0

PHP で完全に機能する nesetd セット システムを
使用しています。これを使用して、最大深度 = 2 のシンプルなメニュー構造を構築しています。

ここで、すべてのメニュー項目の表示状態、つまりアクティブかどうかを制御する追加フ​​ィールドをテーブルに追加しました。私の必要性は、親を非アクティブ化した場合、アクティブであってもクエリが子を返さないようにしたいということです。

これは、メニュー ツリー全体を取得するための実際のコードです。

SELECT    `nesty`.*,
          (COUNT(`parent`.`id`) - (`sub_tree`.`depth` + 1)) AS `depth`

FROM      `menus` AS `nesty`,
          `menus` AS `parent`,
          `menus` AS `sub_parent`,
          (
             SELECT `nesty`.`id`,
                    (COUNT(`parent`.`id`) - 1) AS `depth`

             FROM   `menus` AS `nesty`,
                    `menus` AS `parent`

             WHERE  `nesty`.`lft`  BETWEEN `parent`.`lft` AND `parent`.`rgt`
             AND    `nesty`.`id`     = 1
             AND    `nesty`.`tree_id`  = 1
             AND    `parent`.`tree_id` = 1

             GROUP BY `nesty`.`id`

             ORDER BY `nesty`.`lft`
          ) AS `sub_tree`

WHERE    `nesty`.`lft`   BETWEEN `parent`.`lft`     AND `parent`.`rgt`
AND      `nesty`.`lft`   BETWEEN `sub_parent`.`lft` AND `sub_parent`.`rgt`
AND      `sub_parent`.`id` = `sub_tree`.`id`
AND      `nesty`.`tree_id`   = 1
AND      `parent`.`tree_id`  = 1
GROUP BY `nesty`.`id`

HAVING   `depth` > 0

ORDER BY `nesty`.`lft`

だから基本的にwhere句を追加したい

AND      `nesty`.`visible`   = 1

非アクティブ化されたアイテムが誰かの親ではない限り、うまく機能していることを追加すると、可視フィールドが0に等しい場合、および/またはその親の可視フィールドが0に等しい場合、メニューアイテムが返されないことが必要です

事前にt​​hnx

4

4 に答える 4

0

さて、あなたは追加しようとしましたか:

and (nesty.visible <> 0 and parent.visible <> 0)
于 2013-03-26T18:18:23.577 に答える
0

まず、あなたが投稿した非常に読みやすい SQL ステートメントについて、おめでとうございます。そうでなければ、私はそれに時間を費やすことはなかったでしょう。

残念ながら、私はまだステートメントを理解するのが難しいと感じており、ステートメントはそれほど複雑であってはならないと考えずにはいられません。ネストされたセットは、ツリーの各レベルのテーブルを参照することを避けることで、再帰クエリを正確に単純にすることになっています。これは、あなたがしていることのようです。

メニューのサブツリーを取得するクエリは、次のように単純にする必要があります。

select menus.*
from menus
where menus.id between [plft] and [prgt]

ここで、plft と prgt は、サブツリーのルート ノードの左と右の値によって定義されるパラメーターです。メイン ツリーのルートに id=1 がある場合、次のように記述できます。

select menus.*
from menus
where menus.id between (select lft from menus where id=1) and 
                       (select rgt from menus where id=1)

この典型的なネストされたセットクエリに基づいて、テストされていない回答を提供します。

最初のステップは、明示的に非表示のノード、非表示のサブクエリを特定することです。

select menus.id, lft, rgt
from   menus
where  menus.visible = 0

2 番目のステップでは、暗黙的に非表示になっているすべてのサブツリーを取得します。サブクエリ hidden_​​all:

select menus.id
from
    (select id, lft, rgt
     from   menus
     where  menus.visible = 0) as hidden
inner join menus 
on (menus.lft between hidden.lft and hidden.rgt)

最後のステップでは、サブクエリ hidden_​​all 以外のすべてのメニュー オプションを取得します。これは、外部結合または演算子 IN を使用して行うことができます。最後のオプションを使用する:

select menus.*
from   menus
where  menus.lft between plft and prgt
       and not menus.id in (
    select    menus.id
    from      (select m.id, m.lft, m.rgt
               from   menus m
               where  m.visible = 0) as hidden
    inner join menus m
    on         (m.lft between hidden.lft and hidden.rgt)
    )

前に述べたように、これはテストされておらず、plft と prgt を正しい値に置き換えるか、パラメーターにする必要があります。

于 2013-03-26T22:04:32.790 に答える
0

あなたが参照しているパッケージとそのクエリを書きました。これは、Mike Hillyer によるこのブログ投稿に基づいています。

Modified Preorder Tree Traversal アルゴリズムを使用して、親に対する各結果の「深さ」属性を取得するために、3 つの暗黙的な結合が使用されます。

私が通常行ったことは、あなたがやっているように、データベースからノードのツリーを取得することです。それらをレンダリングするときは、各ノードの「可視性」プロパティを見てください。CRUDモデルを使用して、標準で使用していると思います。そう:

// ノードをループする if ( ! $node->visibility) continue;

クエリから結果を出力しているときに、そのようなことを行うことができます。

Nested-Sets 2 では、Nesty の書き換えにより、illuminate/database(仮想的に) 単純な SQL だけでなく、クエリ ビルダーを使用してそのクエリが記述されます。クロージャーなどを挿入して、クエリを変更できます。

于 2013-03-27T20:55:43.817 に答える
0

申し訳ありませんが、ネストライブラリは本当に悪い技術です。これは、ネストされたセットの実装として理想的とは言えません。深度は決して計算されるべきではありません。ウィキペディアhttp://en.wikipedia.org/wiki/Nested_set_modelに示されているように、深度フィールドはデータ モデルの一部である必要があります。さらに、完全なツリーを返すために上記のクエリを使用しないでください。その複雑さはすべて、サブツリーにのみ必要です。

この新しいパッチを試してください:

= AND      `parent`.`tree_id`  = 1
+ and      nesty.lft not in (
         select menus.lft
         from   menus,
                (select     lft, rgt
                 from       menus
                 where      menus.visible = 0
                 and        menus.tree_id = 1
                ) as hidden
         where  menus.lft between hidden.lft and hidden.rgt
         and    menus.tree_id = 1
                          )

また、テーブル メニューに深度フィールドが含まれている場合、完全なツリーの完全なクエリは次のようになります。

select     nesty.*, 0 as depth0
from       menus as nesty,
           (select lft, rgt from menus where menus.id = 1) as root
where      nesty.lft between root.lft and root.rgt
and        nesty.tree_id  = 1
and        not nesty.lft in (
                select    menus.lft
                from      menus,
                          (select lft, rgt
                           from   menus
                           where  visible = 0
                           and    menus.tree_id = 1
                          ) as hidden
                where     menus.lft between hidden.lft and hidden.rgt
                and       menus.tree_id = 1
                            )
于 2013-03-28T13:29:57.380 に答える