当前位置:Gxlcms > 数据库问题 > MySQL递归查询,实现上下级联查,父子级查询

MySQL递归查询,实现上下级联查,父子级查询

时间:2021-07-01 10:21:17 帮助过:172人阅读

最近在工作当中,遇见了有ztree关系的查询:

比如:根据父级的部门ID查询所有的子级部门;

根据父级的区划代码查询所属下级的所有区划信息;

根据子级ID查询隶属行政区划信息;

根据组织机构ID查询所有子级组织机构;

 

数据准备

为了测试,我们首先来创建一张拥有上下级关系的表,这里选择创建一张区划信息表

  1. <span style="color: #000000;">DROP TABLE IF EXISTS `tb_area`;
  2. CREATE TABLE `tb_area` (
  3. `area_id` </span><span style="color: #0000ff;">int</span>(10<span style="color: #000000;">) unsigned NOT NULL AUTO_INCREMENT,
  4. `area_name` varchar(</span>255<span style="color: #000000;">) DEFAULT NULL,
  5. `area_code` varchar(</span>255<span style="color: #000000;">) DEFAULT NULL,
  6. `pid` </span><span style="color: #0000ff;">int</span>(10<span style="color: #000000;">) DEFAULT NULL,
  7. PRIMARY KEY (`area_id`)
  8. ) ENGINE</span>=InnoDB AUTO_INCREMENT=131 DEFAULT CHARSET=<span style="color: #000000;">utf8;
  9. </span>

 

准备数据:

这里给了一些测试数据,如果需要可以参考:

抓取国家统计局区划数据

可以测试数据:

  1. <code class="hljs">INSERT INTO `tb_area` VALUES (‘1‘, ‘中国‘, ‘100000‘, ‘0‘);
  2. INSERT INTO `tb_area` VALUES (‘2‘, ‘广西壮族自治区‘, ‘450000000000‘, ‘1‘);
  3. INSERT INTO `tb_area` VALUES (‘3‘, ‘防城港市‘, ‘450600000000‘, ‘2‘);
  4. INSERT INTO `tb_area` VALUES (‘4‘, ‘港口区‘, ‘450602000000‘, ‘3‘);
  5. INSERT INTO `tb_area` VALUES (‘5‘, ‘防城区‘, ‘450603000000‘, ‘3‘);
  6. INSERT INTO `tb_area` VALUES (‘6‘, ‘上思县‘, ‘450621000000‘, ‘3‘);
  7. INSERT INTO `tb_area` VALUES (‘7‘, ‘东兴市‘, ‘450681000000‘, ‘3‘);
  8. INSERT INTO `tb_area` VALUES (‘8‘, ‘渔州坪街道‘, ‘450602001000‘, ‘4‘);
  9. INSERT INTO `tb_area` VALUES (‘9‘, ‘白沙叶街道‘, ‘450602002000‘, ‘4‘);
  10. INSERT INTO `tb_area` VALUES (‘10‘, ‘沙潭江街道‘, ‘450602003000‘, ‘4‘);
  11. INSERT INTO `tb_area` VALUES (‘11‘, ‘王府街道‘, ‘450602004000‘, ‘4‘);
  12. INSERT INTO `tb_area` VALUES (‘12‘, ‘企沙镇‘, ‘450602100000‘, ‘4‘);
  13. INSERT INTO `tb_area` VALUES (‘13‘, ‘光坡镇‘, ‘450602101000‘, ‘4‘);
  14. INSERT INTO `tb_area` VALUES (‘14‘, ‘水营街道‘, ‘450603001000‘, ‘5‘);
  15. INSERT INTO `tb_area` VALUES (‘15‘, ‘珠河街道‘, ‘450603002000‘, ‘5‘);
  16. INSERT INTO `tb_area` VALUES (‘109‘, ‘文昌街道‘, ‘450603003000‘, ‘5‘);
  17. INSERT INTO `tb_area` VALUES (‘110‘, ‘大菉镇‘, ‘450603101000‘, ‘5‘);
  18. INSERT INTO `tb_area` VALUES (‘111‘, ‘华石镇‘, ‘450603102000‘, ‘5‘);
  19. INSERT INTO `tb_area` VALUES (‘112‘, ‘那梭镇‘, ‘450603103000‘, ‘5‘);
  20. INSERT INTO `tb_area` VALUES (‘113‘, ‘那良镇‘, ‘450603104000‘, ‘5‘);
  21. INSERT INTO `tb_area` VALUES (‘114‘, ‘峒中镇‘, ‘450603105000‘, ‘5‘);
  22. INSERT INTO `tb_area` VALUES (‘115‘, ‘茅岭镇‘, ‘450603106000‘, ‘5‘);
  23. INSERT INTO `tb_area` VALUES (‘116‘, ‘江山镇‘, ‘450603107000‘, ‘5‘);
  24. INSERT INTO `tb_area` VALUES (‘117‘, ‘扶隆镇‘, ‘450603108000‘, ‘5‘);
  25. INSERT INTO `tb_area` VALUES (‘118‘, ‘滩营乡‘, ‘450603204000‘, ‘5‘);
  26. INSERT INTO `tb_area` VALUES (‘119‘, ‘十万山瑶族乡‘, ‘450603209000‘, ‘5‘);
  27. INSERT INTO `tb_area` VALUES (‘120‘, ‘思阳镇‘, ‘450621100000‘, ‘6‘);
  28. INSERT INTO `tb_area` VALUES (‘121‘, ‘在妙镇‘, ‘450621101000‘, ‘6‘);
  29. INSERT INTO `tb_area` VALUES (‘122‘, ‘华兰镇‘, ‘450621102000‘, ‘6‘);
  30. INSERT INTO `tb_area` VALUES (‘123‘, ‘叫安镇‘, ‘450621103000‘, ‘6‘);
  31. INSERT INTO `tb_area` VALUES (‘124‘, ‘南屏瑶族乡‘, ‘450621203000‘, ‘6‘);
  32. INSERT INTO `tb_area` VALUES (‘125‘, ‘平福乡‘, ‘450621204000‘, ‘6‘);
  33. INSERT INTO `tb_area` VALUES (‘126‘, ‘那琴乡‘, ‘450621206000‘, ‘6‘);
  34. INSERT INTO `tb_area` VALUES (‘127‘, ‘公正乡‘, ‘450621208000‘, ‘6‘);
  35. INSERT INTO `tb_area` VALUES (‘128‘, ‘东兴镇‘, ‘450681100000‘, ‘7‘);
  36. INSERT INTO `tb_area` VALUES (‘129‘, ‘江平镇‘, ‘450681101000‘, ‘7‘);
  37. INSERT INTO `tb_area` VALUES (‘130‘, ‘马路镇‘, ‘450681102000‘, ‘7‘);</code>
技术图片

 

代码编写

首先我们来写自下而上的查询:

也就是根据下级区划代码ID查询隶属行政区

创建一个函数:

  1. <span style="color: #000000;">DROP FUNCTION IF EXISTS getAreaChildBottomUp;
  2. CREATE FUNCTION getAreaChildBottomUp(areaId INT)
  3. RETURNS VARCHAR(</span>4000<span style="color: #000000;">)
  4. BEGIN
  5. DECLARE sTemp VARCHAR(</span>4000<span style="color: #000000;">);
  6. DECLARE sTempChd VARCHAR(</span>4000<span style="color: #000000;">);
  7. SET sTemp</span>=‘$‘<span style="color: #000000;">;
  8. SET sTempChd </span>=<span style="color: #000000;"> CAST(areaId AS CHAR);
  9. SET sTemp </span>= CONCAT(sTemp,‘,‘<span style="color: #000000;">,sTempChd);
  10. SELECT pid INTO sTempChd FROM tb_area WHERE area_id </span>=<span style="color: #000000;"> sTempChd;
  11. WHILE sTempChd </span><> 0<span style="color: #000000;"> DO
  12. SET sTemp </span>= CONCAT(sTemp,‘,‘<span style="color: #000000;">,sTempChd);
  13. SELECT pid INTO sTempChd FROM tb_area WHERE area_id </span>=<span style="color: #000000;"> sTempChd;
  14. END WHILE;
  15. RETURN sTemp;
  16. END;</span>

 

技术图片

 

查询方法:

  1. <span style="color: #000000;">SELECT
  2. </span>*<span style="color: #000000;">
  3. FROM
  4. tb_area
  5. WHERE
  6. FIND_IN_SET(
  7. area_id,
  8. getAreaChildBottomUp (</span>113<span style="color: #000000;">)
  9. );</span>

 

 

显示结果:

技术图片技术图片?

 

也可以直接使用SQL语句:

  1. <span style="color: #000000;">SELECT
  2. area_id,
  3. area_name,
  4. area_code,
  5. pid
  6. FROM
  7. (
  8. SELECT
  9. @r AS _id,
  10. (
  11. SELECT
  12. @r :</span>=<span style="color: #000000;"> pid
  13. FROM
  14. tb_area
  15. WHERE
  16. area_id </span>=<span style="color: #000000;"> _id
  17. ) AS parent_id,
  18. @l :</span>= @l + 1<span style="color: #000000;"> AS lvl
  19. FROM
  20. (SELECT @r :</span>= 113, @l := 0<span style="color: #000000;">) vars,
  21. tb_area h
  22. WHERE
  23. @r </span><> 0<span style="color: #000000;">
  24. ) T1
  25. JOIN tb_area T2 ON T1._id </span>=<span style="color: #000000;"> T2.area_id
  26. ORDER BY
  27. area_id;</span>

 

 

查出效果相同:

技术图片技术图片?

 

下来写自上而下的查询:

也就是根据上级区划代码ID查询隶属下级行政区

创建一个函数:

  1. <span style="color: #000000;">DROP FUNCTION IF EXISTS queryChildFromTopToBottom;
  2. CREATE FUNCTION queryChildFromTopToBottom(areaId INT)
  3. RETURNS VARCHAR(</span>4000<span style="color: #000000;">)
  4. BEGIN
  5. DECLARE sTemp VARCHAR(</span>4000<span style="color: #000000;">);
  6. DECLARE sTempChd VARCHAR(</span>4000<span style="color: #000000;">);
  7. SET sTemp</span>=‘$‘<span style="color: #000000;">;
  8. SET sTempChd </span>=<span style="color: #000000;"> CAST(areaId AS CHAR);
  9. WHILE sTempChd IS NOT NULL DO
  10. SET sTemp</span>= CONCAT(sTemp,‘,‘<span style="color: #000000;">,sTempChd);
  11. SELECT GROUP_CONCAT(area_id) INTO sTempChd FROM tb_area WHERE FIND_IN_SET(pid,sTempChd)</span>>0<span style="color: #000000;">;
  12. END WHILE;
  13. RETURN sTemp;
  14. END;</span>

 

 

查询方法:

  1. <span style="color: #000000;">SELECT
  2. </span>*<span style="color: #000000;">
  3. FROM
  4. tb_area
  5. WHERE
  6. FIND_IN_SET(
  7. area_id,
  8. queryChildFromTopToBottom (</span>4<span style="color: #000000;">)
  9. );</span>

 

 

查询结果:

技术图片技术图片?

欢迎关注摘星族,我们首发于微信公众号:

技术图片技术图片?

MySQL递归查询,实现上下级联查,父子级查询

标签:eset   自治区   line   log   tps   resize   container   sel   效果   

人气教程排行