第一篇文章,从某个同行问我的问题开始。
他的问题大概是这样的:自己已经用Oracle的Start with...Connect By实现了树的递归查询,但是现在要求变了,要用MYSQL也实现相同的递归查询树的功能。这个功能是我从以前从未使用到过的,于是,我上网查询、找了一些资料开始做了起来。我喜欢这种“自己每次在帮助了别人的同时又提高了自己”的进步,因为,我始终相信,会分享、会帮助别人的人注定海纳百川。到最后,功夫不多,总算给他提供了解决方案。我的解决方案只是针对同一个表,两个表只需要在方法里增加两个表的连接条件即可。
下面是我的一些MYSQL最终代码可供解决参考:
创建表nodelist:
- CREATE TABLE nodelist(
- id INT PRIMARY KEY, //本节点ID。
- nodename VARCHAR(20), //节点名称,为方便辨别而已。
- pid INT //父节点。
- );
插入表测试数据:
- Insert INTO nodelist VALUES(1,'A',null); //父节点为,即根节点。
- Insert INTO nodelist VALUES(2,'B',1);
- Insert INTO nodelist VALUES(3,'C',1);
- Insert INTO nodelist VALUES(4,'D',2);
- Insert INTO nodelist VALUES(5,'E',3);
- Insert INTO nodelist VALUES(6,'F',3);
- Insert INTO nodelist VALUES(7,'G',5);
- Insert INTO nodelist VALUES(8,'H',7);
- Insert INTO nodelist VALUES(9,'I',8);
- Insert INTO nodelist VALUES(10,'J',8);
创建函数getChildList():
- CREATE FUNCTION `getChildList`(rootId INT) //rootId为你要查询的节点。
- RETURNS VARCHAR(1000)
- BEGIN
- DECLARE pTemp VARCHAR(1000);
- DECLARE cTemp VARCHAR(1000); //两个临时变量
- SET pTemp = '$';
- SET cTemp =cast(rootId as CHAR); //把rootId强制转换为字符。
- WHILE cTemp is not null DO
- SET pTemp = concat(pTemp,',',cTemp); //把所有节点连接成字符串。
- SELECT group_concat(id) INTO cTemp FROM nodelist
- WHERE FIND_IN_SET(pid,cTemp)>0;
- // FIND_IN_SET(str,strlist)的方法网上大把不解释。
- END WHILE;
- RETURN pTemp;
- END
执行方法getChildList(1):
- SELECT getChildList(1);
运行结果如下图:
查询节点为“3”下的所有节点:
- SELECT * FROM nodelist WHERE FIND_IN_SET(id, getChildList(3));
运行结果如下图: