Проверьте, является ли потомок потомком, используя один запрос mysql
Предположим, у меня есть эта таблица
parent | child
1 2
1 3
2 4
4 5
5 6
и я хочу проверить, является ли 6 потомком 1 (что есть).... Могу ли я выполнить это в одном запросе, или мне придется неизбежно получить все данные и обработать их с помощью PHP?
3 ответа
Вы можете пройтись по дереву с помощью рекурсии в MySQL без обработки данных в PHP. MySQL не поддерживает настоящую рекурсию, поэтому вам придется согласиться на некоторые методы рекурсивного преобразования:
Один метод описан в этом вопросе SO, но будет включать изменение ваших таблиц.
Другой метод - использование хранимой функции, которая будет проходить по таблице до тех пор, пока работа не будет выполнена (что в некотором роде рекурсивно). Это, вероятно, будет работать с вашей текущей таблицей, но будет более сложным для достижения.
У меня здесь есть пример, который просматривает таблицу страниц TYPO3 и находит все идентификаторы страниц для данной корневой строки (сравнимо с тем, что вы пытаетесь достичь):
BEGIN
DECLARE _id INT;
DECLARE _parent INT;
DECLARE _next INT;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;
SET _parent = @id;
SET _id = -1;
IF @id IS NULL THEN
RETURN NULL;
END IF;
LOOP
SELECT MIN(uid)
INTO @id
FROM pages
WHERE pid = _parent
AND uid > _id
AND deleted = 0
AND hidden =0;
IF @id IS NOT NULL OR _parent = @start_with THEN
SET @level = @level + 1;
RETURN @id;
END IF;
SET @level := @level - 1;
SELECT uid, pid
INTO _id, _parent
FROM pages
WHERE uid = _parent
AND deleted = 0
AND hidden = 0;
END LOOP;
END
Извините, что сейчас у меня нет времени адаптировать этот пример к вашим потребностям, что делает этот ответ неполным, но я надеюсь, что, тем не менее, это может привести вас на правильный путь.
Для этого в одном запросе требуется рекурсивный синтаксис, который MySQL не поддерживает.
Oracle использует with ... connect by prior
и SqlServer использует CTE (Common Table Expressions) для рекурсии.
По сути, вам придется запрашивать и анализировать с помощью PHP или создать временную таблицу, используя хранимую процедуру, чтобы выполнить рекурсию программно.
Это дерево (или график, если у одного узла может быть более одного родителя)... Каждый узел дерева, которому известно только, является родителем, вы не можете проанализировать древовидную структуру в обратном направлении с помощью одного "прыжка".
Или, лучше, вы могли бы, но только если вы сохраните полный путь от узла к корню дерева в строку базы данных узла, как это...
parent | child | path
1 3 3,1
3 2 2,3,1
И так далее...
Вы также можете прочитать это: O (1) алгоритм, чтобы определить, является ли узел потомком другого узла в дереве с множеством путей?