Как рассчитать глубину узла в родительско-дочерней модели в MySQL?
Мне понадобится глубина, среди прочего, для создания отступа в моем списке (закодированном с помощью PHP).
Как рассчитать глубину узла в родительско-дочерней модели в MySQL?
Мне понадобится глубина, среди прочего, для создания отступа в моем списке (закодированном с помощью PHP).
Это зависит от фактической реализации вашей иерархии в базе данных. Если вы используете модель вложенных наборов (http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ a>) вы можете получить полный путь от родителя к дочернему элементу с помощью одного выбора.
Обновление: хорошо, поскольку вы собираетесь использовать модель списка смежности, я предлагаю сохранить уровень узла в таблице. Это не только даст вам глубину узла в одном запросе, но также позволит вам получить весь путь к этому узлу в одном запросе (хотя этот запрос должен быть сгенерирован динамически):
SELECT n1.name AS lvl1, n2.name as lvl2, n3.name as lvl3, ..., nN.name as lvlN
FROM nodes AS n1
JOIN nodes AS n2 ON n2.parent_id = n1.id
JOIN nodes AS n3 ON n3.parent_id = n2.id
...
JOIN nodes AS nN ON nN.parent_id = n(N-1).id
WHERE nN.id = myChildNode;
Поскольку вы знаете, что ваш узел находится на уровне N, нет необходимости в левых соединениях, и, учитывая соответствующие индексы для id / parent_id, это должно быть достаточно быстро.
Недостатком этого подхода является то, что вам придется обновлять уровень узла. во время перемещения узла, но это должно быть достаточно просто и быстро, поскольку вы будете делать это только для самого узла и его дочерних элементов, а не для большей части таблицы, как вы сделали бы с вложенными множествами.
Это может быть старый вопрос, но я просто хочу, чтобы другие знали, что я нашел решение несколько месяцев назад. Недавно я писал об этом здесь: http://en.someotherdeveloper.com/articles/adjacency-list-model-with-depth-calculation/
Если вы хотите просто скопировать и вставить, вот мой пример. У меня есть табличные проекты с полями ID и PARENT_ID.
DELIMITER $$
DROP FUNCTION IF EXISTS `getDepth` $$
CREATE FUNCTION `getDepth` (project_id INT) RETURNS int
BEGIN
DECLARE depth INT;
SET depth=1;
WHILE project_id > 0 DO
SELECT IFNULL(parent_id,-1)
INTO project_id
FROM ( SELECT parent_id FROM Projects WHERE id = project_id) t;
IF project_id > 0 THEN
SET depth = depth + 1;
END IF;
END WHILE;
RETURN depth;
END $$
DELIMITER ;