一句SQL实现MYSQL的递归查询

众所周知,目前的mysql版本中并不支持直接的递归查询,但是通过递归到迭代转化的思路,还是可以在一句SQL内实现树的递归查询的。这个得益于Mysql允许在SQL语句内使用@变量。以下是示例代码。

创建表格

CREATE TABLE `treenodes` (
    `id` int , -- 节点ID
    `nodename` varchar (60), -- 节点名称
    `pid` int  -- 节点父ID
); 

插入测试数据

复制代码
INSERT INTO `treenodes` (`id`, `nodename`, `pid`) VALUES
('1','A','0'),('2','B','1'),('3','C','1'),
('4','D','2'),('5','E','2'),('6','F','3'),
('7','G','6'),('8','H','0'),('9','I','8'),
('10','J','8'),('11','K','8'),('12','L','9'),
('13','M','9'),('14','N','12'),('15','O','12'),
('16','P','15'),('17','Q','15'),('18','R','3'),
('19','S','2'),('20','T','6'),('21','U','8');
复制代码

查询语句

复制代码
 SELECT id AS ID,pid AS 父ID ,levels AS 父到子之间级数, paths AS 父到子路径 FROM (
     SELECT id,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,'|',id,':', @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,'|',id,':', @pathnodes ,'|') pathall 
        FROM  treenodes, 
    (SELECT @le:=0,@pathlevel:='', @pathall:='',@pathnodes:='') vv
    ORDER BY  pid,id
    ) src
ORDER BY id
复制代码

最后的结果如下:

复制代码
    ID   父ID  父到子之间级数  父到子路径
------  ------  ------------  ---------------
     1       0        0           ,0             
     2       1        1           ,0,1           
     3       1        1           ,0,1           
     4       2        2           ,0,1,2         
     5       2        2           ,0,1,2         
     6       3        2           ,0,1,3         
     7       6        3           ,0,1,3,6       
     8       0        0           ,0             
     9       8        1           ,0,8           
    10       8        1           ,0,8           
    11       8        1           ,0,8           
    12       9        2           ,0,8,9         
    13       9        2           ,0,8,9         
    14      12        3           ,0,8,9,12      
    15      12        3           ,0,8,9,12      
    16      15        4           ,0,8,9,12,15   
    17      15        4           ,0,8,9,12,15   
    18       3        2           ,0,1,3         
    19       2        2           ,0,1,2         
    20       6        3           ,0,1,3,6       
    21       8        1           ,0,8       
复制代码

 http://www.cnblogs.com/dukou/p/4691543.html

 

--创建表
 
DROP  TABLE  IF EXISTS `t_areainfo`;
CREATE  TABLE  `t_areainfo` (
  `id`  int (11)  NOT  '0'  AUTO_INCREMENT,
  ` level int (11)  DEFAULT  '0' ,
  ` name varchar (255)  DEFAULT  '0' ,
  `parentId`  int (11)  DEFAULT  '0' ,
  `status`  int (11)  DEFAULT  '0' ,
  PRIMARY  KEY  (`id`)
ENGINE=InnoDB AUTO_INCREMENT=65  DEFAULT  CHARSET=utf8;

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
--初始数据
 
INSERT  INTO  `t_areainfo`  VALUES  ( '1' '0' '中国' '0' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '2' '0' '华北区' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '3' '0' '华南区' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '4' '0' '北京' '2' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '5' '0' '海淀区' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '6' '0' '丰台区' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '7' '0' '朝阳区' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '8' '0' '北京XX区1' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '9' '0' '北京XX区2' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '10' '0' '北京XX区3' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '11' '0' '北京XX区4' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '12' '0' '北京XX区5' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '13' '0' '北京XX区6' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '14' '0' '北京XX区7' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '15' '0' '北京XX区8' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '16' '0' '北京XX区9' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '17' '0' '北京XX区10' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '18' '0' '北京XX区11' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '19' '0' '北京XX区12' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '20' '0' '北京XX区13' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '21' '0' '北京XX区14' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '22' '0' '北京XX区15' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '23' '0' '北京XX区16' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '24' '0' '北京XX区17' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '25' '0' '北京XX区18' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '26' '0' '北京XX区19' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '27' '0' '北京XX区1' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '28' '0' '北京XX区2' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '29' '0' '北京XX区3' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '30' '0' '北京XX区4' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '31' '0' '北京XX区5' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '32' '0' '北京XX区6' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '33' '0' '北京XX区7' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '34' '0' '北京XX区8' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '35' '0' '北京XX区9' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '36' '0' '北京XX区10' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '37' '0' '北京XX区11' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '38' '0' '北京XX区12' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '39' '0' '北京XX区13' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '40' '0' '北京XX区14' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '41' '0' '北京XX区15' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '42' '0' '北京XX区16' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '43' '0' '北京XX区17' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '44' '0' '北京XX区18' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '45' '0' '北京XX区19' '4' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '46' '0' 'xx省1' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '47' '0' 'xx省2' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '48' '0' 'xx省3' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '49' '0' 'xx省4' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '50' '0' 'xx省5' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '51' '0' 'xx省6' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '52' '0' 'xx省7' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '53' '0' 'xx省8' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '54' '0' 'xx省9' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '55' '0' 'xx省10' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '56' '0' 'xx省11' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '57' '0' 'xx省12' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '58' '0' 'xx省13' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '59' '0' 'xx省14' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '60' '0' 'xx省15' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '61' '0' 'xx省16' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '62' '0' 'xx省17' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '63' '0' 'xx省18' '1' '0' );
INSERT  INTO  `t_areainfo`  VALUES  ( '64' '0' 'xx省19' '1' '0' );

 

采用function获取所有子节点的id

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
--查询传入areaId及其以下所有子节点
DROP  FUNCTION  IF EXISTS queryChildrenAreaInfo;
CREATE  FUNCTION  `queryChildrenAreaInfo` (areaId  INT )
RETURNS  VARCHAR (4000)
BEGIN
DECLARE  sTemp  VARCHAR (4000);
DECLARE  sTempChd  VARCHAR (4000);
 
SET  sTemp =  '$' ;
SET  sTempChd =  cast (areaId  as  char );
 
WHILE sTempChd  is  not  NULL  DO
SET  sTemp = CONCAT(sTemp, ',' ,sTempChd);
SELECT  group_concat(id)  INTO  sTempChd  FROM  t_areainfo  where  FIND_IN_SET(parentId,sTempChd)>0;
END  WHILE;
return  sTemp;
END ;
 
--调用方式
select  queryChildrenAreaInfo(1);
select  from  t_areainfo  where  FIND_IN_SET(id, queryChildrenAreaInfo(1));

 

 

https://zhidao.baidu.com/question/1303213320623933579.html

 https://www.iteye.com/problems/100720

转载于:https://www.cnblogs.com/softidea/p/10271266.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值