mysql树形结构查询_MySQL递归查询所有子节点,树形结构查询

--表结构

CREATE TABLE `address` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`code_value` varchar(32) DEFAULT NULL COMMENT '区域编码',

`name` varchar(128) DEFAULT NULL COMMENT '区域名称',

`remark` varchar(128) DEFAULT NULL COMMENT '说明',

`pid` varchar(32) DEFAULT NULL COMMENT 'pid是code_value',

PRIMARY KEY (`id`),

KEY `ix_name` (`name`,`code_value`,`pid`)

) ENGINE=InnoDB AUTO_INCREMENT=1033 DEFAULT CHARSET=utf8 COMMENT='行政区域表';

--mysql 实现树结构查询

--方法一

CREATE PROCEDURE sp_showChildLst(IN rootId varchar(20))

BEGIN

CREATE TEMPORARY TABLE IF NOT EXISTS tmpLst

(sno int primary key auto_increment,code_value VARCHAR(20),depth int);

DELETE FROM tmpLst;

CALL sp_createChildLst(rootId,0);

select tmpLst.*,address.* from tmpLst,address where tmpLst.code_value=address.code_value order by tmpLst.sno;

END

CREATE PROCEDURE sp_createChildLst(IN rootId varchar(20),IN nDepth INT)

BEGIN

DECLARE done INT DEFAULT 0;

DECLARE b VARCHAR(20);

DECLARE cur1 CURSOR FOR SELECT code_value FROM address where pid=rootId;

DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;

insert into tmpLst values (null,rootId,nDepth);

SET @@max_sp_recursion_depth = 10;

OPEN cur1;

FETCH cur1 INTO b;

WHILE done=0 DO

CALL sp_createChildLst(b,nDepth+1);

FETCH cur1 INTO b;

END WHILE;

CLOSE cur1;

END

--方法二(此方法有线程安全问题)

CREATE PROCEDURE sp_getAddressChild_list(in idd varchar(36))

begin

declare lev int;

set lev=1;

drop table if exists tmp1;

CREATE TABLE tmp1(code_value VARCHAR(36),`name` varchar(50),pid varchar(36) ,levv INT);

INSERT tmp1 SELECT code_value,`name`,pid,1 FROM address WHERE pid=idd;

while row_count()>0

do

set lev=lev+1;

INSERT tmp1 SELECT t.code_value,t.`name`,t.pid,lev from address t join tmp1 a on t.pid=a.code_value AND levv=lev-1;

end while ;

INSERT tmp1 SELECT code_value,`name`,pid,0 FROM address WHERE code_value=idd;

SELECT * FROM tmp1;

end

--方法三

CREATE FUNCTION fn_getAddress_ChildList_test(rootId INT) RETURNS varchar(1000) CHARSET utf8 #rootId为你要查询的节点

BEGIN

#声明两个临时变量

DECLARE temp VARCHAR(1000);

DECLARE tempChd VARCHAR(1000);

SET temp = '$';

SET tempChd=CAST(rootId AS CHAR);#把rootId强制转换为字符

WHILE tempChd is not null DO

SET temp = CONCAT(temp,',',tempChd);#循环把所有节点连接成字符串。

SELECT GROUP_CONCAT(code_value) INTO tempChd FROM address where FIND_IN_SET(pid,tempChd)>0;

END WHILE;

RETURN temp;

END

--方法四

CREATE PROCEDURE sp_findAddressChild(iid varchar(50),layer bigint(20))

BEGIN

/*创建接受查询的临时表 */

create temporary table if not exists tmp_table(id varchar(50),code_value varchar(50),name varchar(50),pid VARCHAR(50)) ENGINE=InnoDB DEFAULT CHARSET=utf8;

/*最高允许递归数*/

SET @@max_sp_recursion_depth = 10 ;

call sp_iterativeAddress(iid,layer);/*核心数据收集*/

select * from tmp_table ;/* 展现 */

drop temporary table if exists tmp_table ;/*删除临时表*/

END

CREATE PROCEDURE sp_iterativeAddress(iid varchar(50),layer bigint(20))

BEGIN

DECLARE t_id INT;

declare t_codeValue varchar(50) default iid ;

declare t_name varchar(50) character set utf8;

declare t_pid varchar(50) character set utf8;

/* 游标定义 */

declare cur1 CURSOR FOR select id,code_value,`name`,pid from address where pid=iid ;

declare CONTINUE HANDLER FOR SQLSTATE '02000' SET t_codeValue = null;

/* 允许递归深度 */

if layer>0 then

OPEN cur1 ;

FETCH cur1 INTO t_id,t_codeValue,t_name,t_pid ;

WHILE ( t_codeValue is not null )

DO

/* 核心数据收集 */

insert into tmp_table values(t_id,t_codeValue,t_name,t_pid);

call sp_iterativeAddress(t_codeValue,layer-1);

FETCH cur1 INTO t_id,t_codeValue,t_name,t_pid ;

END WHILE;

end if;

END

--方法五 SQL实现

SELECT `name`,code_value AS code_value,pid AS 父ID ,levels AS 父到子之间级数, paths AS 父到子路径 FROM (

SELECT `name`,code_value,pid,

@le:= IF (pid = 0 ,0,

IF( LOCATE( CONCAT('|',pid,':'),@pathlevel) > 0 ,

SUBSTRING_INDEX( SUBSTRING_INDEX(@pathlevel,CONCAT('|',pid,':'),-1),'|',1) +1

,@le+1) ) levels

, @pathlevel:= CONCAT(@pathlevel,'|',code_value,':', @le ,'|') pathlevel

, @pathnodes:= IF( pid =0,',0',

CONCAT_WS(',',

IF( LOCATE( CONCAT('|',pid,':'),@pathall) > 0 ,

SUBSTRING_INDEX( SUBSTRING_INDEX(@pathall,CONCAT('|',pid,':'),-1),'|',1)

,@pathnodes ) ,pid ) )paths

,@pathall:=CONCAT(@pathall,'|',code_value,':', @pathnodes ,'|') pathall

FROM address,

(SELECT @le:=0,@pathlevel:='', @pathall:='',@pathnodes:='') vv

ORDER BY pid,code_value

) src

ORDER BY pid

--方法6  存储过程(SQL实现)

create procedure query_all_add_children(in inPid varchar(50))

begin

select id,code_value,name,remark,pid,p2id,p3id,p4id,p5id

from(

select a1.id,a1.code_value,a1.name,a1.remark,

a1.pid,a2.pid p2id,a3.pid p3id,a4.pid p4id,a5.pid p5id

from

address a1 left join address a2

on(a1.pid=a2.code_value)

left join address a3

on(a2.pid=a3.code_value)

left join address a4

on(a3.pid=a4.code_value)

left join address a5

on(a4.pid=a5.code_value)

) al

where

(pid=inPid

or p2id=inPid

or p3id=inPid

or p4id=inPid

or p5id=inPid

);

end

个人的一些理解:我是用的方法一:取出所有节点利用MySql函数截取所需要的字符串,然后在SQL中字段IN(调用此方法)来进行查询,这样效率比较高,方法6效率也较高,其他方法都有效率问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答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的一些特性,实现递归查询树形结构的存储。但需要注意的是,这种方法可能会对数据库性能造成一定的影响,因此在实际应用中需要根据具体情况进行优化和调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值