0
点赞
收藏
分享

微信扫一扫

一句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

​​--创建表​​

​​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;​​

 

​​--初始数据​​

​​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

 

​​--查询传入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​​​​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​​



举报

相关推荐

0 条评论