MySQL查询树形结构的数据

本文共 4,049 字,预计阅读时间 13 分钟

在项目中经常会遇到树形结构的数据,如何去根据需要去查询也显得尤为重要。

其中表结构如下:

复制代码
CREATE TABLE `s_region` (
  `region_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '行政区编码',
  `region_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '行政区名称',
  `parent_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '上级行政区编码',
  `all_parent` varchar(4000) DEFAULT NULL COMMENT '所有父级节点的编码',
  PRIMARY KEY (`region_code`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
复制代码

注:all_parent字段可根据实际需求决定是否使用。

添加数据

复制代码
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('110000', '北京市', '0', '110000');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('110100', '市辖区', '110000', '110000,110100');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('110101', '东城区', '110100', '110000,110100,110101');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('110102', '西城区', '110100', '110000,110100,110102');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('110105', '朝阳区', '110100', '110000,110100,110105');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('420000', '湖北省', '0', '420000');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('420100', '武汉市', '420000', '420000,420100');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('420103', '江汉区', '420100', '420000,420100,420103');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('420106', '武昌区', '420100', '420000,420100,420106');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('420111', '洪山区', '420100', '420000,420100,420111');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('420115', '江夏区', '420100', '420000,420100,420115');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('420200', '黄石市', '420000', '420000,420200');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('420204', '下陆区', '420200', '420000,420200,420204');
INSERT INTO `cmdp_auth`.`s_region`(`region_code`, `region_name`, `parent_code`, `all_parent`) VALUES ('420222', '阳新县', '420200', '420000,420200,420222');
复制代码

1)需求1:查询当前节点的所有父级节点信息

复制代码
set @tempCode='要查询的编码'; 
SELECT
    T2.* 
FROM
    (
    SELECT
        @R AS rid,
        ( SELECT @R := parent_code FROM s_region WHERE region_code = rid ) AS parent_code,
        @L := @L + 1 AS LVL 
    FROM
        ( SELECT @R := @tempCode, @L := 0) VARS, s_region h
        WHERE @R >= 0 ) T1
        INNER JOIN s_region T2 ON T1.rid = T2.region_code 
ORDER BY
    T1.LVL DESC;
复制代码

其中@tempCode为临时变量,是实际的mybatis的xml中,直接使用变量替换即可。

如查询北京市西城区的所有父级信息,查询结果如下:

2)需求2:查询当前节点的所有子级节点信息

复制代码
set @tempCode='要查询的编码' ;   
select t3.* from (
    select t1.*,
           if(find_in_set(parent_code, @pids) > 0, @pids := concat(@pids, ',', region_code), 
                     if (t1.region_code = @tempCode,@tempCode,0)) as ischild
               from (
                     select t.* from s_region t
                ) t1,
           (select @pids :=  @tempCode) t2
        ) t3 where ischild != 0
复制代码

如要查询湖北省武汉市的所有子节点:

当然上述在查询子节点时,当树形结构子节点数据太大时,查询效率会降低

这里字段all_arent就派上用场了,这个字段存的是所有父级和自身节点的编码,便于查询。此字段需要根据实际需求去决定是否使用,因为这种方式采用的是使用空间换时间。树形结构的数据类似一棵树,子节点是横向与扩展,会存在子节点的数据非常庞大。而此字段存储的是所有的父节点的编码,只要树的深度不是很大,那么其内容就不会很大。

select * from s_region where find_in_set('420100',all_parent)

当然提高了查询的效率,那么在数据更新时,是需要根据实际情况去更新all_parent字段的值。

posted @   钟小嘿  阅读(7337)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2021-10-14 MySQL create table as与create table like对比
2019-10-14 SpringBoot基础
点击右上角即可分享
微信分享提示