mysql 迭代查询,查询所有上级,查询所有下级

两种方法,首先感谢转载的两位大神。



一 SQL直查

1 查询所有上级路径

传送门:http://www.cnblogs.com/dukou/p/4691543.html 

主原文如下

创建表格

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

2 简单改造下查询所有下级,方法较笨,尝试上面直查的方式但没成功,望有大神提供直查的语句学习。

select id 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
 where LOCATE(',2',paths)   > 0  order by id
其中 最后" ,2"为要查询的参数ID,就是查询 id =2的所有下级。


二 MYSQL 自定义函数

1 查询所有下级

传送门:https://zhidao.baidu.com/question/1303213320623933579.html

1
2
3
4
5
6
7
8
9
10
11
--创建表
 
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));
mysql中函数不支持递归调用,仅仅在存储过程中支持!NND老子都写好了一查才TM知道!。

这种查询结果包含了查询ID自己的ID,改了个不包括自己id的

DROP FUNCTION IF EXISTS queryChildrenDepts;
CREATE FUNCTION `queryChildrenDepts` (dpId BIGINT)
RETURNS VARCHAR(4000)
BEGIN
DECLARE sTemp VARCHAR(4000);
DECLARE sTempChd VARCHAR(4000);
SET sTemp = '$';
SET sTempChd = cast(dpId as char);
WHILE sTempChd is not NULL DO
SELECT group_concat(dp_id) INTO sTempChd FROM depts where FIND_IN_SET(dp_belong,sTempChd)>0;
if(sTempChd is null) then 
SET sTemp = sTemp;
else 
SET sTemp = CONCAT(sTemp,',',sTempChd);
end if;
END WHILE;
return sTemp;
END;



2 查询所有上级。

没什么技术含量,反来就是了。

DROP FUNCTION IF EXISTS queryParentDepts;
CREATE FUNCTION `queryParentDepts` (parentId BIGINT)
RETURNS VARCHAR(4000)
BEGIN
DECLARE sTemp VARCHAR(4000);
DECLARE sTempChd VARCHAR(4000);
SET sTemp = '$';
SET sTempChd = cast(parentId as char);
WHILE sTempChd is not NULL DO
SELECT group_concat(dp_belong) INTO sTempChd FROM depts where FIND_IN_SET(dp_id,sTempChd)>0;
if(sTempChd is null) then 
SET sTemp = sTemp;
else 
SET sTemp = CONCAT(sTemp,',',sTempChd);
end if;
END WHILE;
return sTemp;
END;


你可能感兴趣的:(DB,数据库)