1

カテゴリの階層を含めるために、ネストされたセットのように機能する MySQL テーブルがあります。テーブル スキーマは次のようになります。

CREATE TABLE IF NOT EXISTS `categories` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(200) NOT NULL,
  `parent_id` int(11) default NULL,
  `lft` int(11) default NULL,
  `rgt` int(11) default NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `index_categories_on_parent_id_and_name` (`parent_id`,`name`)
)

lftrgtノードの左右の境界を定義し (ネストされたセットが機能する方法は、各ノードの ID がその親の境界内に収まるようにすることです)、親ノードを指定parent_idします。一意のインデックスにより、同じ親を持たない限り、同じ名前の複数のカテゴリが存在できます。

階層に基づいて、セット内の特定のノードを見つける適切な方法を見つけようとしています。たとえば、foo/bar/baz を探す場合、親が bar という名前で、親が foo という名前の baz という名前のノードを取得したいと考えています。明らかに、名前だけで検索することはできません。同じ名前のカテゴリが複数存在する可能性があるからです。

これを行う方法は、最上位のカテゴリを見つけてから、親 ID が以前に見つかったカテゴリのものである指定された名前を持つ後続の各カテゴリを見つけることですが、これはあまり効率的ではないようです。ネストされたセットを検索するより良い方法はありますか?

4

3 に答える 3

1

ネストされたセットでこれを行うための完全にクリーンで効率的な方法があるとは思いません。非正規化された列にノードの祖先のリストを格納すると、これが効率的に提供されますが、実装することはお勧めしません。

ただし、1つのクエリであり、既に持っているインデックスに便利にヒットする、OK'ishメソッドがあります。ターゲット ノードの深さのレベルごとに 1 つの結合を見ています。

あなたの例では foo-bar-baz

select c3.*
from categories c1
inner join categories c2 on c2.parent_id = c1.id AND c2.name = 'bar'
inner join categories c3 on c3.parent_id = c2.id AND c2.name = 'baz'
where c1.name = 'foo'

これは最善の方法ではありませんが、大量の非正規化された情報を保存する努力をしたくない場合は、おそらく最善の策です。コードで SQL を生成するのもかなり簡単です。

于 2009-08-16T04:44:24.663 に答える
1
TopVar = 'foo'
MidVar = 'bar'
BotVar = 'baz'

SELECT D0.*
FROM categories D0, categories D1, categories D2
WHERE D0.name = :BotVar
  AND D0.lft > D1.lft
  AND D0.rgt < D1.rgt
  AND D1.name = :MidVar
  AND D1.lft > D2.lft
  AND D1.rgt < D2.rgt
  AND D2.name = :TopVar;

-アル。

于 2009-08-16T08:01:58.493 に答える
0

私に渡された php プロジェクトでこれを見たことがあります。カテゴリに少なくとも 1 つ、アイテムに 1 つあるので、参加できます..どちらの方法でも、複数のクエリを実行する必要があります

于 2009-08-16T04:16:29.270 に答える