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效率也较高,其他方法都有效率问题。
MySQL递归查询所有子节点,树形结构查询的更多相关文章
- MySql/Oracle树形结构查询
Oracle树形结构递归查询 在Oracle中,对于树形查询可以使用start with ... connect by select * from treeTable start with id='1 ...
- 关于mysql中数据存储复合树形结构,查询时结果按树形结构输出
1.主要思想:根据已有数据,规则性的造数据 select * FROM(select lId,strName,lId as lParentId,-1 as orderIdx from tbClassi ...
- 【MySQL疑难杂症】如何将树形结构存储在数据库中(方案一、Adjacency List)
今天来看看一个比较头疼的问题,如何在数据库中存储树形结构呢? 像mysql这样的关系型数据库,比较适合存储一些类似表格的扁平化数据,但是遇到像树形结构这样有深度的人,就很难驾驭了. 举个栗子:现在有一 ...
- Oracle树形结构查询(递归)
引用:https://blog.csdn.net/u012615705/article/details/78321022 文章转自上述地址,内部有稍许改动,如有需要请查看原文. oracle树状结构 ...
- orcale 树形结构查询
接到需求是要在一个表中(表结构为主键id和父id)循环显示数据,类似于省市县++这种情况 也可能不只有三级子菜单 id name parentid 1 a 0 2 ...
- Delphi中accesss实现树形结构查询系统(一次性生成比较方便)
主要是要读取数据库的信息,而delphi界面是一个树形结构. 例如有一个Ascess数据库:示例.MDB,内有一张表:“国家”,表的内容如下: 编号 名称 01 ...
- sql:sql server,MySQL,PostgreSQL的表,视图,存储过程结构查询
sql server 2005: --SQL SERVER 2005 生成代码需要知道的SQL语句 use LibrarySystem --查询当前数据库所有表和其的主键字段,字段类型,长度,是否为空 ...
- Oracle恢复删除数据 && connect by 树形结构查询
1.一个表中根据以父子级别关系查询显示出来(如图) select t.* from department t CONNECT BY PRIOR t.depid=t.supdepid ; --这样也可以 ...
- sql:MySQL 6.7 表,视图,存储过程结构查询
#数据库MySQL 6.7 use sakila; #查询表名 show tables; # SELECT TABLE_NAME,TABLE_ROWS FROM INFORMATION_SCHEMA. ...
随机推荐
- 极简易版专家聊天程序--JAVA练手
呵呵,用JAVA包开发SOCKET连接,是很简单的呢~~~ DailyAdviceServer.java import java.io.*; import java.net.*; public cla ...
- POJ2115 C Looooops(数论)
题目链接. 分析: 数论了解的还不算太多,解的时候,碰到了不小的麻烦. 设答案为x,n = (1<<k), 则 (A+C*x) % n == B 即 (A+C*x) ≡ B (mod n) ...
- BZOJ1629: [Usaco2007 Demo]Cow Acrobats
1629: [Usaco2007 Demo]Cow Acrobats Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 601 Solved: 305[Su ...
- -_-#【模块】getElementsByClassName
if (!document.getElementsByClassName) { document.getElementsByClassNameForMobile = function(search) ...
- HDOJ 1056 HangOver(水题)
Problem Description How far can you make a stack of cards overhang a table? If you have one card, yo ...
- goodAddr
http://www.tuicool.com/articles/ZV7vya [tungsten'实时'同步mysql数据到mongodb]
- Fork 一个仓库并同步
Fork 一个示例仓库 Fork 是对一个仓库的克隆.克隆一个仓库允许你自由试验各种改变,而不影响原始的项目. 一般来说,forks 被用于去更改别人的项目(贡献代码给已经开源的项目)或者使用别人的项 ...
- BaseAdapter的ArrayIndexOutOfBoundsException
最近写一个listView中多个listItem布局时,convertView缓存及使用,类似微信的聊天界面的listView,报了一个异常: 11-25 15:51:49.076: E/InputE ...
- SQL基础--> 约束(CONSTRAINT)
--============================= --SQL基础--> 约束(CONSTRAINT) --============================= 一.几类数据完 ...
- XCode5/Apple LLVM 5.0下使用boost的方法
Because Apple changes the compiler to llvm only in XCode5, so there are some compatible problems wit ...