数据库:sql 递归

mysql 自关联表,以下为向下递归以及向上递归样例。

1 递归查询前期准备,如果你的表已经存在,可忽略此步。
  • 建表
CREATE TABLE `wq_areainfo` (
 `id` int(11) NOT null 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` (`id`, `level`, `name`, `parentId`, `status`) VALUES (1, 0, '中国', 0, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (2, 0, '华北区', 1, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (3, 0, '华南区', 1, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (4, 0, '北京', 2, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (5, 0, '海淀区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (6, 0, '丰台区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (7, 0, '朝阳区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (8, 0, '大兴区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (9, 0, '东城区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (10, 0, '西城区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (11, 0, '崇文区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (12, 0, '宣武区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (13, 0, '石景山区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (14, 0, '门头沟区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (15, 0, '房山区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (16, 0, '通州区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (17, 0, '顺义区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (18, 0, '昌平区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (19, 0, '怀柔区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (20, 0, '平谷区', 4, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (46, 0, '吉林省', 1, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (47, 0, '黑龙江', 46, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (48, 0, '哈尔滨', 46, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (49, 0, '大连', 46, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (50, 0, '沈阳', 46, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (63, 0, '松原', 46, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (64, 0, '吉林市', 46, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (65, 0, '葫芦岛', 46, 0);
INSERT INTO `t_areainfo` (`id`, `level`, `name`, `parentId`, `status`) VALUES (66, 0, '扶余', 46, 0);
2 向下递归查询当前节点下所有子节点以及籽籽节点
  • 利用find_in_set()函数和group_concat()函数实现递归查询
    其中:group_concat(): 多条记录合成一条记录 ;find_in_set(str, strlist) : 在多条记录中查询特定列 ,str 要查询的字符串 ,strlist 字段名 参数以”,”分隔 如 (1,2,6,8):
DROP FUNCTION IF EXISTS queryChildren;
CREATE FUNCTION queryChildren(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;
END WHILE;
RETURN sTemp;
END;
  • 调用方式
SELECT queryChildren(1);

这里写图片描述
- 查询id为”4”下面的所有节点

SELECT * FROM wq_areainfo WHERE FIND_IN_SET(id,queryChildren(4));

这里写图片描述

3 向上递归查询所有父亲以及父亲的父亲
DROP FUNCTION IF EXISTS queryParents;
CREATE FUNCTION queryParents(areaId INT)
RETURNS VARCHAR(4000)
BEGIN
DECLARE sTemp VARCHAR(4000);
DECLARE sTempChd VARCHAR(4000);

SET sTemp='$';
SET sTempChd = CAST(areaId AS CHAR);
SET sTemp = CONCAT(sTemp,',',sTempChd);

SELECT parentId INTO sTempChd FROM t_areainfo WHERE id = sTempChd;
WHILE sTempChd <> 0 DO
SET sTemp = CONCAT(sTemp,',',sTempChd);
SELECT parentId INTO sTempChd FROM t_areainfo WHERE id = sTempChd;
END WHILE;
RETURN sTemp;
END;
  • 查询id为47的父亲以及父亲的父亲,无限递归查询上一代。
    SELECT * from t_areainfo where FIND_IN_SET(id,queryParents(47));
    这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_17033579/article/details/82216035