MySQL查找树形结构中某个节点及其子节点

目录

问题

如何解决

方法1:使用 MySQL 变量 + 函数

 方法2:维护一个 path 字段


问题

设计表结构存储树形结构数据时,一般使用 parentId 来记录当前节点的父id。

表结构如下所示(以MySQL为例)

create table test
(
    id           varchar(30) collate utf8mb4_general_ci default '' not null
        primary key,
    name         varchar(100) collate utf8mb4_general_ci           null,
    parentId     varchar(30) collate utf8mb4_general_ci            null comment '父分类id'
)
    comment 'test';

查询出全部数据后通过每个节点各自的 parentId 就能够构造出整棵树。

但是,有些时候只想找到某个节点下的所有子节点,如果还是要查全表后构造整棵树再去查找目标节点,就显得很繁琐

如何解决

方法1:使用 MySQL 变量 + 函数

查询目标节点以及所有子节点,返回所有节点id,用【,】拼接

select GROUP_CONCAT(id) from (SELECT @ids as id,
                                      (SELECT @ids := GROUP_CONCAT(id) FROM test
                                       WHERE FIND_IN_SET(parentId, CONVERT(@ids USING utf8mb4) COLLATE utf8mb4_0900_ai_ci)
                                      ) AS childrenId
                               FROM test, (SELECT @ids := '节点id') var
                                WHERE @ids IS NOT NULL) t

 同理,使用该方法还可以用来查询目标节点以及所有父节点

SELECT GROUP_CONCAT(id)  FROM
    (SELECT @id AS id,
            (SELECT @id := parentId FROM test WHERE id = CONVERT(@id USING utf8mb4) COLLATE utf8mb4_0900_ai_ci) AS pid
     FROM test, ( SELECT @id := '节点id') var WHERE @id IS NOT NULL) t

 方法2:维护一个 path 字段

方法1的查询语句其实不好理解,不便后期维护。

(经评论区提醒,如果id之间存在包含关系的话,就不适用了)如果id字段长度固定的话,可以给表新增一个path字段。

create table test
(
    id           varchar(30) collate utf8mb4_general_ci default '' not null
        primary key,
    name         varchar(100) collate utf8mb4_general_ci           null,
    parentId     varchar(30) collate utf8mb4_general_ci            null comment '父分类id',
    path         varchar(500)                                      null comment 'id路径,逗号隔开'
)
    comment 'test';

path字段维护当前节点的所有父节点id,用【,】拼接

比如C节点的父节点是B,B节点的父节点是A,A是根节点

那么

C节点的path字段就为:A节点id,B节点id,C节点id

B节点的path字段就为:A节点id,B节点id

A节点的path字段就为:A节点id

然后根据path字段模糊查询便可以找到目标节点以及子节点了

select id from test where path like ‘%节点id%’ 

  • 39
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: MySQL实现递归查找树形结构可以通过使用WITH RECURSIVE和UNION ALL语句来实现。以下是一个示例查询: 假设我们有一个名为“category”的表,其包含以下列:id、name和parent_id,其parent_id列包含一个指向同一表的父类别的外键。 我们可以使用以下查询递归地查找树形结构: ``` WITH RECURSIVE category_tree (id, name, parent_id, depth) AS ( SELECT id, name, parent_id, 0 FROM category WHERE parent_id IS NULL # 根节点 UNION ALL SELECT c.id, c.name, c.parent_id, ct.depth + 1 FROM category c JOIN category_tree ct ON c.parent_id = ct.id ) SELECT id, name, parent_id, depth FROM category_tree; ``` 在此查询,我们首先选择根节点,然后使用UNION ALL语句递归地选择所有子节点。使用WITH RECURSIVE语句和递归查询,我们可以轻松地构建树形结构,并根据需要进行任何进一步的处理。 ### 回答2: MySQL是一种关系型数据库管理系统,它本身并不支持递归查询,但可以通过多表联接和递归实现树形结构查询。 在MySQL,可以使用两种方式来实现树形结构的递归查询:使用递归函数或使用临时表。 使用递归函数可以实现树形结构的递归查询,该函数可以通过递归的方式查询树形结构子节点,并将结果集逐层汇总。递归函数通常包括两部分:基准查询和递归查询。基准查询用于获取初始节点的直接子节点,递归查询则用于获取每个子节点子节点,依次类推。通过将基准查询和递归查询结合起来,并使用UNION ALL将结果集合并,就可以得到完整的树形结构。然后可以使用JOIN等操作将查询结果与其他表进行联接,实现更复杂的查询功能。 另一种方式是使用临时表来实现树形结构的递归查询。首先,创建一个临时表,其包含树形结构节点和其父节点的信息。然后使用一个循环将树形结构节点逐层加入到临时表,直到所有节点都被添加进去。最后,使用JOIN等操作将临时表与其他表进行联接,实现需要的查询功能。 无论使用哪种方式,实现树形结构的递归查询都需要注意两个问题:首先是递归的结束条件,即确定递归何时停止;其次是性能问题,树形结构可能非常复杂,递归查询消耗的资源和时间都较大,需要综合考虑查询效率和系统性能。 总的来说,通过合理地使用递归函数或临时表,结合适当的查询操作,可以在MySQL实现树形结构的递归查询,并完成需要的查询功能。 ### 回答3: MySQL是一种关系型数据库管理系统,它本身不支持递归查询树形结构的存储。但是,我们可以利用MySQL的一些特性来实现递归查找树形结构。 实现递归查询树形结构的方法有很多种,以下是其一种常用的方法: 1. 为每个节点添加一个字段,用于记录节点的父节点ID; 2. 创建一个递归查询函数,用于查找节点子节点,并将结果保存到一个临时表; 3. 递归调用该函数,直到找到所有节点子节点; 4. 使用JOIN语句将各个临时表连接起来,得到完整的树形结构。 具体步骤如下: 1. 创建一个表来存储树形结构节点信息,表包含节点ID、节点名称和父节点ID等字段; 2. 创建一个存储递归查询结果的临时表; 3. 创建一个存储递归调用所需参数的存储过程或函数,参数包括父节点ID、递归深度和临时表名等; 4. 在存储过程或函数,使用SELECT INTO语句查询满足条件的子节点,并将结果插入到临时表; 5. 在存储过程或函数,使用递归调用语句调用自身,并传递子节点作为父节点ID; 6. 在存储过程或函数,使用条件判断语句来停止递归,例如判断是否已经到达最深层级或没有更多子节点; 7. 在主程序,调用存储过程或函数,并使用JOIN语句将各个临时表连接起来,得到完整的树形结构。 通过以上步骤,我们可以利用MySQL的一些特性,实现递归查询树形结构的存储。但需要注意的是,这种方法可能会对数据库性能造成一定的影响,因此在实际应用需要根据具体情况进行优化和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值