假设我有这个表
parent | child
1 2
1 3
2 4
4 5
5 6
我想检查 6 是否是 1 的后代(确实如此)....我可以在一个查询中完成此操作,还是必须不可避免地获取所有数据并使用 PHP 处理它们?
您可以在MySQL中使用递归遍历树,而无需在PHP中处理数据。MySQL不支持真正的递归,所以你必须接受一些递归技术:
此 SO 问题中描述了一种方法,但涉及更改表。
另一种方法是使用存储函数,该函数将遍历表,直到作业完成(在某种程度上是递归的)。这可能适用于您当前的表,但实现起来更复杂。
我这里有一个例子,它遍历一个 TYPO3 页面表,找到给定根行的所有页面 ID(与您试图实现的目标相当):
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
请原谅我现在没有时间根据您的需求定制此示例,使这是一个不完整的答案,但我希望这仍然可以让您走上正确的轨道。
那是一棵树(如果一个节点可以有多个父节点,则是一个图形)...树的每个节点只知道父节点,你不能用一个"跳"向后解析树结构。
或者更好,你可以,但前提是你将从节点到树根的完整路径保存到节点数据库行中,就像这样......
parent | child | path
1 3 3,1
3 2 2,3,1
等等...
你也可以读到这个: O(1) 算法来确定节点是否是多路树中另一个节点的后代?
要在单个查询中执行此操作需要递归语法,而mysql不支持。Oracle 使用 with ... connect by prior
,SqlServer 使用 CTE(Common Table Expressions)进行递归。
本质上,您必须使用 PHP 进行查询和分析,或者使用存储过程创建一个临时表,以编程方式执行递归。