9

私は最近、ネストされたセットモデルのがらくたを使用しています。私は、ほぼすべての有用な操作とビューのクエリを楽しく設計してきました。私が行き詰まっていることの 1 つは、ノードの直接の子 (および子のみであり、それ以上の子孫ではない!) を選択する方法です。

正直なところ、私はその方法を知っていますが、それには手に負えない量の SQL が含まれます。もっと簡単な解決策があると確信しています。

4

6 に答える 6

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」を埋め込むので、ノードの子を簡単に要求できます。

于 2009-03-18T18:39:53.367 に答える
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

つまり、「問題のノードのすべての子孫から、それら自身とノードの間に祖先がないものを選択する」ということです。

于 2009-03-19T09:40:00.007 に答える
6

これはより良く、より小さくなります

ユーザー「bobince」はほとんどそれを持っていました。私はそれを理解し、それが私のために機能するようになりました。なぜなら、私はほとんどの場合よりも少し多くのMySQLの経験を持っているからです。しかし、ボビンスの答えが人々を怖がらせる理由はわかります。彼の質問は不完全です。最初に、mysql変数でparent_leftとparent_rightを選択する必要があります。

tree以下の2つのクエリは、テーブルの名前が、左の列の名前がlft、右の列の名前rgtが、主キーの名前がであると想定していますid。ニーズに合わせてこれらの値を変更してください。また、最初の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
于 2010-01-15T15:51:35.233 に答える
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

于 2014-09-01T01:41:30.730 に答える
0

深度列も使用します。しかし、使用

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

ウィキペディア

于 2011-11-09T07:54:36.653 に答える
0

私はnecroの投稿をしていることを知っていますが、これが私の意見です。

ネストされたセットに「深さ」列を含めてみませんか? 深さの列はアイテムの「レベル」を示します。

したがって、アイテムの直接の子を選択するには、次のようにします

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

于 2011-02-01T03:33:01.910 に答える