千家信息网

SQL 中怎么利用双亲节点查找所有子节点

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这期内容当中小编将会给大家带来有关SQL 中怎么利用双亲节点查找所有子节点,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。创建表如下CREATE TABLE cate
千家信息网最后更新 2026年11月01日SQL 中怎么利用双亲节点查找所有子节点

这期内容当中小编将会给大家带来有关SQL 中怎么利用双亲节点查找所有子节点,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

创建表如下

CREATE TABLE category ( id LONG, parentId LONG, name String(20) )INSERT INTO category VALUES ( 1, NULL, 'Root' )INSERT INTO category VALUES ( 2, 1, 'Branch2' )INSERT INTO category VALUES ( 3, 1, 'Branch3' )INSERT INTO category VALUES ( 4, 3, 'SubBranch2' )INSERT INTO category VALUES ( 5, 2, 'SubBranch3' )

其中,parent id 表示父节点, name 是节点名称。

假设当前欲获取某一节点下所有子节点(获取后代 Descendants),该怎么做呢?如果使用程序(Java/PHP)递归调用,那么将在数据库与本地开发语言之间来回访问,效率之低可想而知。于是我们希望在数据库的层面就可以完成,--该怎么做呢?

递归法

经查询,最好的方法(个人觉得)是 SQL 递归 CTE 的方法。所谓 CTE 是 Common Table Expressison 公用表表达式的意思。网友评价说:"CTE 是一种十分优雅的存在。CTE 所带来最大的好处是代码可读性的提升,这是良好代码的必须品质之一。使用递归 CTE 可以更加轻松愉快的用优雅简洁的方式实现复杂的查询。"--其实我对 SQL 不太熟悉,大家谷歌下其意思即可。

怎么用 CTE 呢?我们用小巧数据库 SQLite,它就支持!别看他体积不大,却也能支持最新 SQL99 的 with 语句,例子如下。

WITH w1( id, parentId, name) AS (SELECT category.id, category.parentId,             category.nameFROM category WHERE id = 1UNION ALL SELECT category.id, category.parentId,             category.nameFROM category JOIN w1 ON category.parentId= w1.id)

SELECT * FROM w1;其中 WHERE id = 1 是那个父节点之 id,你可以改为你的变量。简单说,递归 CTE 最少包含两个查询(也被称为成员)。第一个查询为定点成员,定点成员只是一个返回有效表的查询,用于递归的基础或定位点。第二个查询被称为递归成员,使该查询称为递归成员的是对 CTE 名称的递归引用是触发。在逻辑上可以将 CTE 名称的内部应用理解为前一个查询的结果集。递归查询没有显式的递归终止条件,只有当第二个递归查询返回空结果集或是超出了递归次数的最大限制时才停止递归。递归次数上限的方法是使用 MAXRECURION。

相应地给出查找所有父节点的方法(获取祖先 Ancestors,就是把 id 和 parentId 反过来)

WITH w1( id, parentId, name, level) AS  (    SELECT          id,          parentId,          name,        0 AS level      FROM          category        WHERE          id = 6     UNION ALL        SELECT          category.id,          category.parentId,          category.name ,        level + 1      FROM          category JOIN w1 ON category.id= w1.parentId )  SELECT * FROM w1;

无奈的 MySQL

SQLite ok 了,而 MySQL 呢?

在另一边厢,大家都爱用的 MySQL 却无视 with 语句,官网博客上明确说明是压根不支持,十分不方便,明明可以很简单事情为什么不能用呢?--而且 MySQL 也好像没有计划在将来的新版本中添加 with 的 cte 功能。于是大家想出了很多办法。其实不就是一个递归程序么--应该不难--写函数或者存储过程总该行吧?没错,的确如此,--写递归不是问题,问题是用 SQL 写就是个问题--还是那句话,"隔行如隔山",虽然有点夸张的说法,但我想既懂数据库又懂各种数据库方言写法(存储过程)的人应该不是很多吧~,--不细究了,反正就是代码帖来贴去呗~

我这里就不贴 SQL 了,可以看这里的,《MySQL中进行树状所有子节点的查询》

至此,我们的目的可以说已经达到了,而且还不错,因为这是不限层数的(以前 CMS 常说的"无限级"分类)。--其实,一般情况下,层数超过三层就很多,很复杂了,一般用户如无特殊需求,也用不上这么多层。于是,在给定层数的约束下,可以写标准的 SQL 来完成该任务--尽管有点写死的感觉~~

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4FROM category AS t1LEFT JOIN category AS t2 ON t2.parentId = t1.idLEFT JOIN category AS t3 ON t3.parentId = t2.idLEFT JOIN category AS t4 ON t4.parentId = t3.idWHERE t1.id= 1

相应地给出查找所有父节点的方法(获取祖先 Ancestors,就是把 id 和 parentId 反过来)

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4 FROM category AS t1 LEFT JOIN category AS t2 ON t2.id= t1.parentId LEFT JOIN category AS t3 ON t3.id= t2.parentId LEFT JOIN category AS t4 ON t4.id= t3.parentId

WHERE t1.id= 10优化版本

但是生成的结果和第一个例子相比起来有点奇怪,而且不好给 Java 用,--那就再找找其他例子

SELECT p1.id, p1.name, p1.parentId as parentId, p2.parentId as parent2_id, p3.parentId as parent3_id, p4.parentId as parent4_id, p5.parentId as parent5_id,p6.parentId as parent6_idFROMcategory p1LEFT JOIN category p2 on p2.id = p1.parentId LEFT JOIN category p3 on p3.id = p2.parentId LEFT JOIN category p4 on p4.id = p3.parentId LEFT JOIN category p5 on p5.id = p4.parentId LEFT JOIN category p6 on p6.id = p5.parentIdWHERE 1 IN (p1.parentId, p2.parentId, p3.parentId, p4.parentId, p5.parentId, p6.parentId)

ORDER BY 1, 2, 3, 4, 5, 6, 7; 这个总算像点样子了,结果是这样子的。

相应地给出查找所有父节点的方法(获取祖先 Ancestors,就是把 id 和 parentId 反过来, 还有改改 IN 里面的字段名)

SELECT           p1.id,         p1.name,         p1.parentId as parentId,         p2.parentId as parent2_id,         p3.parentId as parent3_id  FROM  category p1   LEFT JOIN  category p2 on p2.parentId  = p1.id  LEFT JOIN  category p3 on p3.parentId  = p2.id  WHERE 9 IN  (p1.id,              p2.id,              p3.id)    ORDER BY 1, 2, 3;

这样就很通用啦~无论你 SQLite 还是 MySQL。

其他查询:

查询直接子节点的总数:

SELECT c.*,    (SELECT COUNT(*) FROM category c2 WHERE c2.parentId = c.id)     AS direct_childrenFROM category c

上述就是小编为大家分享的SQL 中怎么利用双亲节点查找所有子节点了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

递归 节点 查询 就是 方法 成员 数据 数据库 结果 代码 例子 反过来 名称 祖先 问题 支持 双亲 复杂 最大 优雅 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 中国互联网科技股 科技与互联网发展 现代科技和互联网有关系吗 广州慧亚互联网科技怎么样 昭通云南众福互联网科技有限公司 银川新华互联网科技职业技术培训学校图片 互联网系的金融科技公司 昭通互联网科技选哪家 互联网科技公司有风险吗 想开互联网科技公司怎么样 互联网科技人工智能实验室 为客找房互联网科技公司怎么样 互联网公司高科技产品 广州燕处互联网科技有限公司 互联网金融运营模式中的金融科技 互联网科技创新创业项目 青岛互联网科技园 上海旺乐尼互联网科技有限公司 瑞安市蟠桃会互联网科技有限公司 互联网科技创业有什么好项目 咖啡网 博彦科技互联网金融 哈尔滨大商圈互联网科技有限公司 科技信息互联网 互联网科技金融 互联网科技寓意 南山科技园互联网公司有哪些 互联网科技商业 合肥互联网科技公司公章图片 卡尔迅互联网科技有限公司
0