众所周知,目前的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`) |
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 ( \'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 ); return sTemp; END ; --调用方式 select queryChildrenAreaInfo(1); select * from t_areainfo where FIND_IN_SET(id, queryChildrenAreaInfo(1)); |