使用MySQL 8递归查询获取指定父ID的所有后代ID
解决MySQL递归CTE查询所有子孙节点的问题
你的递归CTE存在两个核心错误:
- 字段不匹配:CTE声明了
(concept_id, parent_id)两个字段,但初始查询只返回了concept_id AS child_id,不仅字段数量不符,还错误使用别名child_id,导致后续递归时找不到该列。 - 递归逻辑错误:递归部分没有关联原表获取下一级子节点,仅从
runner中重复选取数据,无法实现层级遍历。
正确的递归CTE实现
以下是针对需求的正确写法,以查询父ID为1的所有子孙节点为例:
WITH RECURSIVE runner (concept_id, parent_id) AS ( -- 锚点成员:获取指定父ID的直接子节点 SELECT concept_id, parent_id FROM concept_has_parent_concepts WHERE parent_id = 1 UNION ALL -- 递归成员:以上一级的concept_id作为父ID,获取下一级子节点 SELECT c.concept_id, c.parent_id FROM concept_has_parent_concepts c JOIN runner r ON c.parent_id = r.concept_id ) -- 最终查询所有子孙节点的concept_id SELECT concept_id FROM runner;
代码解释
- 锚点成员:直接从原表筛选出父ID等于目标值的记录,作为递归的起始节点(直接子节点)。
- 递归成员:通过
JOIN关联runner(已遍历的节点)和原表,将runner中的concept_id作为父ID,去原表中匹配对应的子节点,以此实现深度遍历所有层级的子孙。
动态指定父ID
如果需要动态传入父ID,可以使用变量:
SET @target_parent_id = 300264091; WITH RECURSIVE runner (concept_id, parent_id) AS ( SELECT concept_id, parent_id FROM concept_has_parent_concepts WHERE parent_id = @target_parent_id UNION ALL SELECT c.concept_id, c.parent_id FROM concept_has_parent_concepts c JOIN runner r ON c.parent_id = r.concept_id ) SELECT concept_id FROM runner;
验证结果
针对你提供的示例数据:
- 查询父ID为
1时,返回结果为3,4,7,8,9,10,符合预期。 - 查询父ID为
2时,返回结果为5,6,符合预期。
内容的提问来源于stack exchange,提问作者Jeroen Steen
相关产品推荐
相关产品推荐

