mysql 递归查询子节点

14 篇文章 1 订阅

表结构及数据与oracle递归查询子节点中的一致

数据结构稍有不同

drop table if EXISTS city;
create table city(
id int primary key,
name varchar(50) not null,
parent_id int
);

sql

1.找出所有的节点

select id,name,parent_id from city t order by parent_id, id 

2.如果节点的 父id 在 选择的节点id中 将该节点添加到选择的节点集合中(递归)

select t1.id,t1.name,parent_id,
              if(find_in_set(parent_id, @pids) > 0, @pids := concat(@pids, ',', id), 0) as ischild
              from ( select id,name,parent_id from city t order by parent_id, id ) t1,
                  (select @pids := 2) t2

3.最后将所有子节点返回

select id,name,ischild from (
              select t1.id,t1.name,
              if(find_in_set(parent_id, @pids) > 0, @pids:= concat(@pids, ',', id), 0) as ischild
              from ( 
                    select id,name,parent_id from city t order by parent_id, id 
                  ) t1,
                  (select @pids:= 选择的节点id) t2
             ) t3 
where ischild != 0;

关键方法

find_in_set(str,strList) :查询字段(strlist)中包含(str)的结果

    参数:str 要查询的字符串,strlist 字段名 参数以”,”分隔 如 (1,2,6,8)

    结果:不包含——0, 包含——返回第一个存在的位置:select FIND_IN_SET('2', '1,2,6,8'); 结果 2

if(express1,express2,express3):当exprss1成立时,执行express2,否则执行express3;

自定义函数实现

获取所有下级节点id

drop function if EXISTS getChildren;
CREATE FUNCTION getChildren (city_id INT) RETURNS VARCHAR (4000)
BEGIN
DECLARE result VARCHAR (4000);
DECLARE child VARCHAR (4000);
SET result = '';
SET child = CAST(city_id AS CHAR);
WHILE child IS NOT NULL DO
SET result = CONCAT(result, ',', child);
SELECT
	GROUP_CONCAT(id) INTO child
FROM
	city
WHERE
	FIND_IN_SET(parent_id, child) > 0;
END
WHILE;
RETURN result;
END

调用

select * from city where FIND_IN_SET(id,getChildren(2));

方法/关键字说明

表达式 into 变量名 将 表达式的值插入到变量中(赋值)

group_concat([distinct]要连接的字段 [order by 排序字段 asc/desc] [separator '分隔符']) : 将group by 产生的同一个分组中的值连接起来,返回一个字符串结果

    说明:通过使用 distinct 可以去重;如果希望对结果进行排序,可以使用 order by; separator 是一个字符串,缺省为一个逗号,用于分隔连接的字段

    注意:若没有明确有group by 语句时,将所有满足条件的结果作为一个分组

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要在MySQL中进行查询节点,可以使用以下方法: 1. 使用归CTE(Common Table Expressions): 在MySQL 8.0版本及以上,可以使用归CTE来实现查询归CTE允许在查询归引用同一表,并在每次迭代中执行归步骤。例如: ```sql WITH RECURSIVE sub_tree AS ( SELECT id, parent_id, name FROM t_files WHERE id = <初始节点ID> UNION ALL SELECT f.id, f.parent_id, f.name FROM t_files f JOIN sub_tree st ON f.parent_id = st.id ) SELECT * FROM sub_tree; ``` 上述查询中,使用了一个归CTE查询`sub_tree`,它首先选择初始节点,然后通过归连接`t_files`表自身,直到找到所有节点。 2. 使用存储过程: 如果您的MySQL版本不支持归CTE,可以通过编写存储过程来实现查询。存储过程可以使用循环和条件语句来逐级查询节点。以下是一个示例存储过程: ```sql DELIMITER // CREATE PROCEDURE get_child_nodes(IN initial_id INT) BEGIN DECLARE done INT DEFAULT FALSE; DECLARE current_id INT; DECLARE child_id INT; DECLARE child_name VARCHAR(255); DECLARE cur CURSOR FOR SELECT id, name FROM t_files WHERE parent_id = initial_id; DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; CREATE TEMPORARY TABLE IF NOT EXISTS temp_results (id INT, name VARCHAR(255)); OPEN cur; read_loop: LOOP FETCH cur INTO child_id, child_name; IF done THEN LEAVE read_loop; END IF; INSERT INTO temp_results VALUES (child_id, child_name); CALL get_child_nodes(child_id); END LOOP; CLOSE cur; SELECT * FROM temp_results; DROP TEMPORARY TABLE IF EXISTS temp_results; END // DELIMITER ; ``` 在上述存储过程中,通过使用游标和归调用存储过程来获取所有节点,并将结果存储在一个临时表中。 以上是两种常用的方法来在MySQL中进行查询节点。您可以根据您的具体需求选择适合您的方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

day day day ...

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值