首页 运维知识 有关一句SQL实现MYSQL的递归查询

有关一句SQL实现MYSQL的递归查询

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

众所周知,目前的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
--创建表
DROP TABLE IF EXISTS `t_areainfo`;
CREATE TABLE `t_areainfo` (
 `id` int(11) NOT \'0\' AUTO_INCREMENT,
 `levelint(11) DEFAULT \'0\',
 `namevarchar(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;
return sTemp;
--调用方式
select queryChildrenAreaInfo(1);
select from t_areainfo where FIND_IN_SET(id, queryChildrenAreaInfo(1));
免责声明:文章内容不代表本站立场,本站不对其内容的真实性、完整性、准确性给予任何担保、暗示和承诺,仅供读者参考,文章版权归原作者所有。如本文内容影响到您的合法权益(内容、图片等),请及时联系本站,我们会及时删除处理。

作者: 小小编

为您推荐

dell R710 更换raid卡后,raid卡信息没有了,处理方案

dell R710 更换raid卡后,raid卡信息没有了,处理方案

1.将一台服务器(A)的硬盘依次拔出,按相同顺序插入另一台同样配置的服务器(B) 2.启动服务器(B) 3.按提示键盘按...
PL SQL Developer 13连接Oracle数据库并导出数据详细操作教程方法

PL SQL Developer 13连接Oracle数据库并导出数据详细操作教程方法

下载 并安装 PL SQL Developer 13,默认支持中文语言 ========================...
关于一条sql语句在mysql中是如何执行的

关于一条sql语句在mysql中是如何执行的

最近开始在学习mysql相关知识,自己根据学到的知识点,根据自己的理解整理分享出来,本篇文章会分析下一个sql语句在my...
关于sql注入姿势总结(mysql)

关于sql注入姿势总结(mysql)

前言 学习了sql注入很长时间,但是仍然没有系统的了解过,这次总结一波,用作学习的资料。 从注入方法分:基于报错、基于布...
关于Oracle SQL外连接

关于Oracle SQL外连接

SQL提供了多种类型的连接方式,它们之间的区别在于:从相互交叠的不同数据集合中选择用于连接的行时所采用的方法不同。 连接...

发表回复

返回顶部