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

?

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

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

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

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

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

数据准备

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

DROP TABLE IF EXISTS `tb_area`;
CREATE TABLE `tb_area` (
`area_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`area_name` varchar(255) DEFAULT NULL,
`area_code` varchar(255) DEFAULT NULL,
`pid` int(10) DEFAULT NULL,
PRIMARY KEY (`area_id`)
) ENGINE=InnoDB AUTO_INCREMENT=131 DEFAULT CHARSET=utf8;

准备数据:

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

抓取国家统计局区划数据

可以测试数据:

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

代码编写

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

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

创建一个函数:

DROP FUNCTION IF EXISTS getAreaChildBottomUp;
CREATE FUNCTION getAreaChildBottomUp(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 pid INTO sTempChd FROM tb_area WHERE area_id = sTempChd;
WHILE sTempChd <> 0 DO
SET sTemp = CONCAT(sTemp,‘,‘,sTempChd);
SELECT pid INTO sTempChd FROM tb_area WHERE area_id = sTempChd;
END WHILE;
RETURN sTemp;
END;

查询方法:

SELECT
*
FROM
tb_area
WHERE
FIND_IN_SET(
area_id,
getAreaChildBottomUp (113)
);

显示结果:

?

也可以直接使用SQL语句:

SELECT
area_id,
area_name,
area_code,
pid
FROM
(
SELECT
@r AS _id,
(
SELECT
          @r := pid
FROM
tb_area
WHERE
area_id = _id
) AS parent_id,
      @l := @l + 1 AS lvl
FROM
(SELECT @r := 113, @l := 0) vars,
tb_area h
WHERE
@r <> 0
) T1
JOIN tb_area T2 ON T1._id = T2.area_id
ORDER BY
area_id;

查出效果相同:

?

下来写自上而下的查询:

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

创建一个函数:

DROP FUNCTION IF EXISTS queryChildFromTopToBottom;
CREATE FUNCTION queryChildFromTopToBottom(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(area_id) INTO sTempChd FROM tb_area WHERE FIND_IN_SET(pid,sTempChd)>0;
END WHILE;
RETURN sTemp;
END;

查询方法:

SELECT
*
FROM
tb_area
WHERE
FIND_IN_SET(
area_id,
queryChildFromTopToBottom (4)
);

查询结果:

?

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

?

原文地址:https://www.cnblogs.com/zhaixingzhu/p/12569272.html

时间: 2024-10-29 22:01:56

MySQL递归查询,实现上下级联查,父子级查询的相关文章

MySQL的多表联查和嵌套查询

1.数据准备 ### 创建表与插入数据准备 ```python #建表 create table dep2( id int, name varchar(20) ); create table emp2( id int primary key auto_increment, name varchar(20), sex enum('male','female') not null default 'male', age int, dep_id int ); #插入数据 insert into dep

Mysql递归查询,无限级上下级菜单

mysql递归查询,mysql中从子类ID查询所有父类(做无限分类经常用到) 由于mysql 不支持类似 oracle with ...connect的 递归查询语法 之前一直以为类似的查询要么用存储过程要么只能用程序写递归查询. 现在发现原来一条sql语句也是可以搞定的 先来看数据表的结构如下: id  name    parent_id ---------------------------  1   Home        0  2   About       1  3   Contact

单纯MYSQL递归查询上下级关系

查询 id = 6 的所有父级 SELECT ID.level, DATA.* FROM( SELECT @id as _id, ( SELECT @id := parent_id FROM table1 WHERE id = @id ) as _pid, @l := @l+1 as level FROM table1, (SELECT @id := 6, @l := 0 ) b WHERE @id > 0 ) ID, table1 DATA WHERE ID._id = DATA.id ORD

一道关于数据库(经典父子级 ID 关联)更新题,大家帮忙想想还有其它解决思路没有?

昨天,一同事发过来的一道数据库题目,就是哪种经典的父子级 ID 在同一数据库表中设计类型.需要在原表中添加一个字段,同时,将该节点的父子级详细信息插入到原表新增的一字段中,具体效果如下图. AreaCode .AreaName.ParentCode (原表三字段). Content __新增字段,更新该 AreaCode 下所有父级菜单信息至新增至原表的 Content 字段下面,用红线框起来(意思应该讲明白了吧.) AreaCode:地区 ID   AreaName:地区介绍    Paren

mysql 递归查询sql语句的实现

SELECT t.ITEM_NAME, t.ITEM_CID, t.ITEM_PID FROM `tlk_案由表单` t WHERE NOT EXISTS( select * from `tlk_案由表单` t1,`tlk_案由表单` t2 where t1.ITEM_CID=t2.ITEM_PID AND t.ITEM_CID=t1.ITEM_CID ) 注意到ITEM_CID和ITEM_PID的位置是有很重要的影响的哟,具体情况执行下sql就明白了! MySql递归查询,mysql中从子类I

php+Mysql 优化,百万至千万级快速分页

php+Mysql 优化,百万至千万级快速分页 MySql 性能到底能有多高?用了php半年多,真正如此深入的去思考这个问题还是从前天开始.有过痛苦有过绝望,到现在充满信心!MySql 这个数据库绝对是适合dba级的高手去玩的,一般做一点1万篇新闻的小型系统怎么写都可以,用xx框架可以实现快速开发.可是数据量到了10万,百万至千万,他的性能还能那么高吗?一点小小的失误,可能造成整个系统的改写,甚至更本系统无法正常运行!好了,不那么多废话了.用事实说话,看例子: 数据表 collect ( id,

MySQL全文索引、联合索引、like查询、json查询速度大比拼

查询背景 有一个表tmp_test_course大概有10万条记录,然后有个json字段叫outline,存了一对多关系(保存了多个编码,例如jy1577683381775) 我们需要在这10万条数据中检索特定类型的数据,目标总数据量:2931条 SELECT COUNT(*) FROM tmp_test_course WHERE `type`=5 AND del=2 AND is_leaf=1 我们在限定为上面类型的同时,还得包含下面任意一个编码(也就是OR查询) jy157768338177

mysql 创建索引、重建索引、查询索引、删除索引 转自:http://www.phpernote.com/mysql/942.html

本篇文章主要是对MySQL索引操作方法做了一下总结,包括创建索引.重建索引.查询索引.删除索引的操作.以下所列示例中中 `table_name` 表示数据表名,`index_name` 表示索引名,column list 表示字段列表(如:`id`,`order_id`). 1.创建索引 索引的创建可以在CREATE TABLE语句中进行,也可以单独用CREATE INDEX或ALTER TABLE来给表增加索引.以下命令语句分别展示了如何创建主键索引(PRIMARY KEY),联合索引(UNI

同级、父子级div定位

以两个div右上角对齐为例: 效果图: 1.同级定位 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <met