Есть ли простой способ запросить дочерние узлы? - PullRequest
9 голосов
/ 18 марта 2009

В последнее время я пользуюсь дерьмом из модели вложенного набора . Мне нравилось создавать запросы практически для каждой полезной операции и вида. Одна вещь, на которой я застрял, - это как выбрать непосредственных потомков (и только потомков, а не дальнейших потомков!) Узла.

Если честно, я знаю способ, но он требует неуправляемого количества SQL. Я уверен, что есть более простое решение.

Ответы [ 6 ]

9 голосов
/ 18 марта 2009

Читали ли вы опубликованную статью? Он находится под заголовком «Найти ближайших подчиненных узла»

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» в таблицу, чтобы я мог легко запросить дочерние элементы узла.

7 голосов
/ 19 марта 2009

Мне кажется, это должно быть легко выполнимо без подзапросов или избыточности родительских столбцов! Например, данные левого и правого родителя уже известны:

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

То есть «из всех потомков рассматриваемого узла выберите тех, у которых нет предков между ними и узлом».

5 голосов
/ 15 января 2010

ЭТО ЛУЧШЕ И МЕНЬШЕ

У пользователя "bobince" его почти нет. Я понял это и заставил его работать на меня, потому что у меня немного больше опыта работы с MySQL, чем у большинства. Однако я понимаю, почему ответ Бобинса может отпугнуть людей. Его запрос не завершен. Вы должны сначала выбрать parent_left и parent_right в переменные mysql.

Два приведенных ниже запроса предполагают, что ваша таблица называется tree, ваш левый столбец - lft, правый столбец - rgt, а ваш первичный ключ - id. Измените эти значения в соответствии с вашими потребностями. Также рассмотрите первое предложение выбора. Вы увидите, что я ищу непосредственных потомков узла 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 голосов
/ 01 сентября 2014

Я нашел Ссылка на Википедию имеет хорошо свернутую версию ответа вместе с выбранным ответом.

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

0 голосов
/ 09 ноября 2011

Я бы тоже пошел с колонкой глубины. Но используйте

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

Википедии

0 голосов
/ 01 февраля 2011

я знаю, что я делаю некро, но вот мое мнение.

почему бы не включить столбец глубины в свой вложенный набор? столбец глубины будет указывать «уровень» элемента.

Итак, чтобы выбрать непосредственных потомков элемента, просто сделайте

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...