2009-03-18 14 views
9

最近、私はNested Set Modelの駄菓を使っています。私はちょうどすべての便利な操作と表示のためのクエリの設計を楽しんでいます。私が執着していることの1つは、直下の子供を選択する方法です(ノード子供、それ以上の子孫ではありません!)。ノードの子を照会する簡単な方法はありますか?

私は方法を知っていますが、それには管理できない量のSQLが含まれています。より簡単な解決策があると確信しています。

答えて

9

投稿した記事を読んだことがありますか?それは私が隣接リストと入れ子になったセットを組み合わせているが、私は何をすべきか(これは浮気された)

SELECT node.name, (COUNT(parent.name) - (sub_tree.depth + 1)) AS depth 
FROM nested_category AS node, 
    nested_category AS parent, 
    nested_category AS sub_parent, 
    (
     SELECT node.name, (COUNT(parent.name) - 1) AS depth 
     FROM nested_category AS node, 
     nested_category AS parent 
     WHERE node.lft BETWEEN parent.lft AND parent.rgt 
     AND node.name = 'PORTABLE ELECTRONICS' 
     GROUP BY node.name 
     ORDER BY node.lft 
    )AS sub_tree 
WHERE node.lft BETWEEN parent.lft AND parent.rgt 
    AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt 
    AND sub_parent.name = sub_tree.name 
GROUP BY node.name 
HAVING depth <= 1 
ORDER BY node.lft; 

の「ノードの直接の部下を探す」の見出しの下だ - 私は、テーブル内の「PARENT_ID」を埋め込みます私はノードの子供たちに簡単に質問することができます。

+0

ハ「...私は、隣接リスト...と、ネストされたセットを組み合わせました」!それは私がやっていることです。私はadjに加入する。 Joe Celkoによるクエリに基づいたリストビュー。それはひどいコードのようです。リンクされた記事のソリューションでさえも...冗長です。 – Metaphile

+0

つまり、ノードの子孫を_all_を選択して比較することを意味します。 SELECT * ノードから どこのノードか。左上のBETWEENのparentLeftBoundとparentRightBound; – Metaphile

+0

まあ、 "child_view"は非常にシンプルです、SELECT * FROMノードwhere parent_id = 123456:D –

7

これは、サブクエリや親カラムの冗長性を持たないと簡単に実行できるはずです。例えば、与えられた親の左と右のは、既に知られている:

ある
SELECT child.id 
FROM nodes AS child 
LEFT JOIN nodes AS ancestor ON 
    ancestor.left BETWEEN @parentleft+1 AND @parentright-1 AND 
    child.left BETWEEN ancestor.left+1 AND ancestor.right-1 
WHERE 
    child.left BETWEEN @parentleft+1 AND @parentright-1 AND 
    ancestor.id IS NULL 

、「問題のノードのすべての子孫からは、自分自身とノードの間には祖先を持つものを選びます」。

+0

パフォーマンス、この1つまたは受け入れられたポストの中で、どちらの方が優れているのでしょうか。しかし、両方のソリューションが機能します。これはもう少しコンパクトに見えます。 – andreas

+0

非常に大きなツリーの場合、MySQLではパフォーマンスが悪く、SQLサーバーではパフォーマンスが悪いことがわかりました。ネストループをデータベースで実行する必要があるためです。すべての子孫を取得するだけでコードを変更した後、アプリケーションコード内の子のみにプルーニングしました。 – user393274

+0

@andreasこれは受け入れられた答えと非常によく似ていますが、違いは、子供を数えて1人の子供にフィルタリングするのではなく、祖先がNULLかどうかを見てフィルタリングすることです。カウントステップ)。それは速くなければならないが、私はそれをテストしていない。 – Ariel

5

THIS ONEは

ユーザー "bobinceは" ほとんどそれを持っていたより良く、小さくなっています。私はそれを理解して、MySQLの経験がもう少し多かったので、私のために働くようにしました。しかし、なぜ私はbobinceの答えが人々を恐れているのかを知ることができます。彼の質問は不完全です。まず、mysql変数にparent_leftとparent_rightを選択する必要があります。以下

2つのクエリは、あなたの左の列が右のカラムがrgt命名され、lftという名前の、そしてあなたの主キーがid命名されていることをされ、あなたのテーブルがtree命名されていることを前提としています。これらの値を必要に応じて変更します。また、最初のselectステートメントを調べます。私はノード5の直下の子孫を探していることがわかります。番号5を変更して、必要なノードの子を探す。

私は個人的にはこれまでよりも洗練された、よりセクシーで、より効率的なクエリだと思います。

SELECT `lft`, `rgt` INTO @parent_left, @parent_right FROM efm_files WHERE `id` = 5; 
SELECT `child`.`id` 
FROM `tree` AS `child` 
LEFT JOIN `tree` AS `ancestor` ON 
    `ancestor`.`lft` BETWEEN @parent_left+1 AND @parent_right-1 AND 
    `child`.`lft` BETWEEN `ancestor`.`lft`+1 AND `ancestor`.`rgt`-1 
WHERE 
    `child`.`lft` BETWEEN @parent_left+1 AND @parent_right-1 AND 
    `ancestor`.`id` IS NULL 
+0

'efm_files'とは何ですか? – Madbreaks

+0

efm_filesは、mysqlデータベース内のテーブルの名前です。データベースの独自のテーブル名に置き換えます。 – mrbinky3000

0

iはネクロポスト、 をやっイムを知っているが、ここで私の意見です。

ネストしたセットに「深度」列を含めないのはなぜですか? 奥行きの列は項目の「レベル」を示します。アイテムの即時チャイルズを選択するので、

は、ちょうど

select c.*
from tree as p
join tree as c on (c.left > p.left and c.right < p.right and c.depth = p.dept + 1) where p.id = @parentID

+0

厳密に言えば、これはもはやネストされたセットではないため、階層モデルの組み合わせです。そして、しばしば問題を解決するためにモデルを変更することは選択肢ではありません。 – Madbreaks

0

を行う私も、深欄で行くと思います。しかし、私はWikipedia linkは、選択した答えと一緒に答えの良い最小化バージョンを持っていた

SELECT Child.Node, Child.LEFT, Child.RIGHT 
FROM Tree AS Child, Tree AS Parent 
WHERE 
     Child.Depth = Parent.Depth + 1 
     AND Child.LEFT > Parent.LEFT 
     AND Child.RIGHT < Parent.RIGHT 
     AND Parent.LEFT = 1 -- Given Parent Node Left Index 

Wikipedia

+0

左右のIDと共に*追加の*深さの列が必要であることに注意してください。 – Youngjae

0

使用しています。

SELECT DISTINCT Child.Name 
FROM ModelTable AS Child, ModelTable AS Parent 
WHERE Parent.Lft < Child.Lft AND Parent.Rgt > Child.Rgt -- associate Child Nodes with ancestors 
GROUP BY Child.Name 
HAVING MAX(Parent.Lft) = @parentId -- Subset for those with the given Parent Node as the nearest ancestor 

そして、あなたがたのうち、LINQのとそれを表現しようとすると、リンクをクリックしてください:https://stackoverflow.com/a/25594386/361100

関連する問題