1. 程式人生 > >Mysql遞迴獲取某個父節點下面的所有子節點和子節點上的所有父節點

Mysql遞迴獲取某個父節點下面的所有子節點和子節點上的所有父節點

在MySQL中自定義函式來實現遞迴獲取所有子節點,該方式的優點是可以減少java程式碼量,缺點是:1.不好維護;2.拼接的欄位太長的時候,自定義函式的返回值可能容量不夠,此時可以定義為text等大容量型別;3:show variables like 'group_concat_max_len'  檢視group_concat的容量為1024 ,具體內容檢視:https://blog.csdn.net/world_ding/article/details/54286862
。還有一個注意點,在生產環境中要給自定義的函式分配許可權,不然可能會沒有許可權請求這個自定義的函式。

1.MySQL表結構和資料

/*
Navicat MySQL Data Transfer

Source Server         : localhost_3306
Source Server Version : 50712
Source Host           : localhost:3306
Source Database       : test

Target Server Type    : MYSQL
Target Server Version : 50712
File Encoding         : 65001

Date: 2018-04-13 12:47:42
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for treenodes
-- ----------------------------
DROP TABLE IF EXISTS `treenodes`;
CREATE TABLE `treenodes` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nodename` varchar(50) DEFAULT NULL,
  `pid` int(11) DEFAULT '0',
  `text` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of treenodes
-- ----------------------------
INSERT INTO `treenodes` VALUES ('1', 'A', '0', null);
INSERT INTO `treenodes` VALUES ('2', 'B', '1', null);
INSERT INTO `treenodes` VALUES ('3', 'C', '1', null);
INSERT INTO `treenodes` VALUES ('4', 'D', '2', null);
INSERT INTO `treenodes` VALUES ('5', 'E', '2', null);
INSERT INTO `treenodes` VALUES ('6', 'F', '3', null);
INSERT INTO `treenodes` VALUES ('7', 'G', '6', null);
INSERT INTO `treenodes` VALUES ('8', 'H', '0', null);
INSERT INTO `treenodes` VALUES ('9', 'I', '8', null);
INSERT INTO `treenodes` VALUES ('10', 'J', '8', null);
INSERT INTO `treenodes` VALUES ('11', 'K', '8', null);
INSERT INTO `treenodes` VALUES ('12', 'L', '9', null);
INSERT INTO `treenodes` VALUES ('13', 'M', '9', null);
INSERT INTO `treenodes` VALUES ('14', 'N', '12', null);
INSERT INTO `treenodes` VALUES ('15', 'O', '12', null);
INSERT INTO `treenodes` VALUES ('16', 'P', '15', null);
INSERT INTO `treenodes` VALUES ('17', 'Q', '15', null);
INSERT INTO `treenodes` VALUES ('18', '一級機構', '7', null);
INSERT INTO `treenodes` VALUES ('19', '二級機構', '18', null);
INSERT INTO `treenodes` VALUES ('20', '三級機構', '19', null);
INSERT INTO `treenodes` VALUES ('21', '銷售經理', '20', null);
INSERT INTO `treenodes` VALUES ('22', '銷售經理2', '21', null);
INSERT INTO `treenodes` VALUES ('23', '代理人', '22', null);
INSERT INTO `treenodes` VALUES ('24', '代理人', '22', null);
INSERT INTO `treenodes` VALUES ('25', '不該出現', null, null);

2.自定義獲取某個父節點下面的所有子節點的函式

CREATE FUNCTION `getChildList`(rootId INT)
RETURNS varchar(1000) 
 
BEGIN
	  #宣告兩個區域性變數
    DECLARE sTemp VARCHAR(1000);
    DECLARE sTempChd VARCHAR(1000);
		#初始化區域性變數
    SET sTemp = '$';
		#呼叫cast函式將int轉換為char
    SET sTempChd =cast(rootId as CHAR);
    #遞迴拼接
    WHILE sTempChd is not null DO
				#儲存每次遞迴結果
        SET sTemp = concat(sTemp,',',sTempChd);
				#將引數作為pid,然後查詢其子id,然後將子id作為pid,
        #查詢以子id為pid的子id,依次迴圈下去,直到所有節點都為葉子節點
        SELECT group_concat(id) INTO sTempChd FROM  treeNodes where FIND_IN_SET(pid,sTempChd)>0;
    END WHILE;
    RETURN sTemp; 
END



#測試
select * from treenodes where FIND_IN_SET(id,getChildList(20));

3.自定義獲取子節點上的所有父節點函式

CREATE FUNCTION `getParList`(rootId INT)
RETURNS varchar(1000) 
BEGIN
    DECLARE sTemp VARCHAR(1000);
    DECLARE sTempPar VARCHAR(1000); 
    SET sTemp = ''; 
    SET sTempPar =rootId; 
 
    #迴圈遞迴
    WHILE sTempPar is not null DO 
        #判斷是否是第一個,不加的話第一個會為空
        IF sTemp != '' THEN
            SET sTemp = concat(sTemp,',',sTempPar);
        ELSE
            SET sTemp = sTempPar;
        END IF;
        SET sTemp = concat(sTemp,',',sTempPar); 
        SELECT group_concat(pid) INTO sTempPar FROM treenodes where pid<>id and FIND_IN_SET(id,sTempPar)>0; 
    END WHILE; 
 
RETURN sTemp; 
END
#測試
select * from treenodes where FIND_IN_SET(id,getParList(15));

4.刪除自定義的函式

DROP FUNCTION `getChildList`;