MySQL вложенные наборы - как найти родителя узла?
у меня есть ваш запуск установки типа иерархии вложенного набора mill со следующими столбцами:
имя таблицы:
myset
столбцы:
id, name, lft, rgt
кто-нибудь знает запрос для определения родитель узла?
Я прочитал пару мест, которые удобно также иметь ид_родительского_объекта столбец в вашей таблице, чтобы отслеживать это, но он кажется избыточным, и кажется, что он может выйти из синхронизации с вложенным набором если запрос был неправильно выполнен при добавлении/удалении / перемещении чего-либо в наборе.
8 ответов
посмотреть этот вопрос. Он похож на ваш. Я отправил туда запрос, который вам может понадобиться.
SELECT title, (SELECT TOP 1 title
FROM tree t2
WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt
ORDER BY t2.rgt-t1.rgt ASC) AS parent
FROM tree t1
ORDER BY rgt-lft DESC
Я надеюсь, что есть то, что вам нужно.
для следующей таблицы:
+-------------+----------------------+-----+-----+
| category_id | name | lft | rgt |
+-------------+----------------------+-----+-----+
| 1 | ELECTRONICS | 1 | 20 |
| 2 | TELEVISIONS | 2 | 9 |
| 3 | TUBE | 3 | 4 |
| 4 | LCD | 5 | 6 |
| 5 | PLASMA | 7 | 8 |
| 6 | PORTABLE ELECTRONICS | 10 | 19 |
| 7 | MP3 PLAYERS | 11 | 14 |
| 8 | FLASH | 12 | 13 |
| 9 | CD PLAYERS | 15 | 16 |
| 10 | 2 WAY RADIOS | 17 | 18 |
он производит выход:
title | parent
----------------------------------------------
ELECTRONICS | NULL
PORTABLE ELECTRONICS | ELECTRONICS
TELEVISIONS | ELECTRONICS
MP3 PLAYERS | PORTABLE ELECTRONICS
FLASH | MP3 PLAYERS
CD PLAYERS | PORTABLE ELECTRONICS
2 WAY RADIOS | PORTABLE ELECTRONICS
TUBE | TELEVISIONS
LCD | TELEVISIONS
PLASMA | TELEVISIONS
TOP-это команда MSSQL, используйте LIMIT для MySQL:
SELECT title, (SELECT title
FROM tree t2
WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt
ORDER BY t2.rgt-t1.rgt ASC
LIMIT 1)
AS parent FROM tree t1
ORDER BY (rgt-lft) DESC
должен сделать трюк ..
просто добавить к этим ответам, которые помогли мне много,
мне нужно было найти непосредственного родителя узла, а также родителя самого верхнего уровня цепочки узлов в некоторых случаях,
я использовал следующее в качестве основы для получения элементов в порядке от ребенка к родителю
SELECT parent.* FROM
nested_set node,
nested_set parent
WHERE (
node.set_left BETWEEN parent.set_left AND parent.set_right
)
AND node.set_id={CHILD_NODE_ID_HERE}
ORDER BY parent.set_right - parent.set_left
#LIMIT 1,1
это потом добавьте LIMIT 1,1
чтобы захватить только вторую строку, которая будет непосредственным родителем
следует также отметить, что с выше запрос если сам узел является родителем самого верхнего уровня, то он не будет иметь непосредственного родителя, поэтому с LIMIT 1,1
он должен возвращать пустой результирующий набор
чтобы получить родитель самого верхнего уровня, я изменил предложение order by, включил проверку, является ли сам узел верхним родителем, и ограничил результат первой строкой
SELECT parent.* AS top_level_right FROM
nested_set node,
nested_set parent
WHERE (
node.set_left >= parent.set_left
AND node.set_left <= parent.set_right
)
AND node.set_id={CHILD_NODE_ID_HERE}
ORDER BY parent.set_left - parent.set_right
LIMIT 1
в последнем запросе я использовал >= <=
операторы, чтобы выбранный диапазон охватывал дочерний узел, если это также происходит с будьте родителем верхнего уровня
у меня была проблема с запросом Лукаша. Моя версия mysql не понимала верхнюю команду. Вместо этого мне пришлось использовать LIMIT. Вот пересмотренный кодекс.
SELECT
`id`,
(SELECT
`id`
FROM
`[*** YOUR TABLE ***]` AS `t2`
WHERE
`t2`.`left_id` < `t1`.`left_id`AND
`t2`.`right_id` > `t1`.`right_id`
ORDER BY
`t2`.`right_id`-`t1`.`right_id`ASC
LIMIT
1) AS `parent`
FROM
`[*** YOUR TABLE ***]` AS `t1`
WHERE
`t1`.`id` = [*** ID OF THE NODE WHOS PARENT YOU WISH TO LOOKUP ***]
ORDER BY
`right_id`-`left_id` DESC
очевидно, измените материал в [ ], чтобы удовлетворить ваши потребности. Также удалите [ ]. Этот запрос возвращает только одну строку. Вот так...
id parent
7 3
SELECT parent.name
FROM myset AS node, myset AS parent
WHERE parent.lft < node.lft
AND parent.rgt > node.rgt
AND node.id = {YOUR CATEGORY ID}
ORDER BY ( parent.rgt - parent.lft ) ASC LIMIT 1;
все предки возвращаются
SELECT id FROM thetable
WHERE x BETWEEN lft and rgt;
таким образом, прямой родитель является предком с наименьшей разницей между lft и rgt.
SELECT id FROM thetable
WHERE x BETWEEN lft and rgt
ORDER BY (rgt-lft)
LIMIT 1
select * from myset
where lft < :lftOfCurrent and rgt > :lftOfCurrent
order lft desc
limit 1
вы можете использовать max, а не order/ limit, и вам может понадобиться другое ключевое слово, чтобы ограничить результаты одной строкой в зависимости от вашей базы данных. Между, а не будет работать, если ваша база данных возвращает эксклюзивный набор, который MySQL не делает.
код от spankmaster79 не был полностью неправильным. Я изменил его код, и он сработал.
SELECT parent . * FROM Nested_Category AS node, Nested_Category AS parent
enter code hereWHERE node.leftSide
BETWEEN parent.leftSide
AND parent.rightSide
AND node.id ='Enter the Node ID'
ORDER BY (
parent.rightSide - parent.leftSide
)
LIMIT 1 , 1