MySQL层级查询实战:无函数实现部门父路径

本次需要击毙的MySQL函数

函数主要用于获取部门的完整层级路径,方便在应用程序或SQL查询中直接调用,快速获得部门的上下级关系信息。执行该函数之后简单使用SQL可以实现数据库中部门名称查询。例如下面sql

select name,GetDepartmentParentNames(du.department_code, du.tenant_id) as department_full_name xxx   from  tableName

CREATE
DEFINER = xxx@`%`
FUNCTION GetDepartmentParentNames(_code VARCHAR(255), _tenant_id VARCHAR(255)) RETURNS TEXT
BEGINDECLARE _name TEXT;DECLARE _parentCode VARCHAR(255);DECLARE _tempName TEXT;DECLARE _tempCode VARCHAR(255);-- 根据传入的部门code和租户id,查询该部门的code、name和父级pidSELECT code, name, pid INTO _tempCode, _tempName, _parentCode FROM table1 WHERE code = _code AND tenant_id = _tenant_id;-- 初始化_name变量,格式为 "code#name"SET _name = CONCAT(_tempCode, '#', _tempName);-- 通过循环,逐级查找父部门,直到父部门pid为'0'(表示无父部门)WHILE _parentCode <> '0' DOSELECT code, name, pid INTO _tempCode, _tempName, _parentCode FROM table1 WHERE code = _parentCode AND tenant_id = _tenant_id;-- 将当前父部门信息拼接到_name前面,格式依然是 "code#name",用逗号分隔SET _name = CONCAT(CONCAT(_tempCode, '#', _tempName), ',', _name);END WHILE;-- 返回拼接好的字符串,包含从顶级父部门到当前部门的所有层级信息RETURN _name;
END;

如何进行重构解决

分析函数的作用是通过递归的方式,基于部门code和tenant_id,逐级向上查找父部门,拼接出完整的部门层级名称字符串。

方案一采用MySQL8+的CTE实现

WITH RECURSIVE dept_path AS (SELECT code, name, pid, CAST(CONCAT(code, '#', name) AS CHAR(1000)) AS full_pathFROM table1WHERE code = #{department_code} AND tenant_id = #{tenant_id}UNION ALLSELECT d.code, d.name, d.pid, CONCAT(CONCAT(d.code, '#', d.name), ',', dp.full_path)FROM table1 dJOIN dept_path dp ON dp.pid = d.codeWHERE d.tenant_id = #{tenant_id} AND d.pid <> '0'
)
SELECT full_path FROM dept_path WHERE pid = '0' LIMIT 1;

但是我不会这个咋办,那就换一种实现方式~

方案二应用层或存储过程外部实现递归

涉及机密下述代码进行过脱敏处理

1. 修改SQL查询部门部分,直接查询用户对应的部门编码和部门名称,不调用递归函数
  <select id="xxxxx" resultType="xxxxxxx">SELECT du.user_code AS code, du.department_code AS departmentNoFROM table1 duWHERE du.tenant_id = #{tenantId}<if test="userCodes != null and userCodes.size() > 0">AND du.user_code IN<foreach collection="userCodes" item="item" separator="," open="(" close=")">#{item}</foreach></if></select>

调用上述方法获取到集合之后需要利用Set集合进行去重

     // 提取所有部门code(包括父部门)用于查询部门信息Set<String> allDeptCodes = new HashSet<>();for (KbUserRoleInfo ud : userDepartments) {allDeptCodes.add(ud.getDepartmentNo());}
2.新增查询部门信息相关信息sql
  <select id="listDepartmentsByCodes" resultType="xxxxxx">SELECT code, name, pidFROM table1WHERE tenant_id = #{tenantId}AND code IN<foreach collection="codes" item="code" separator="," open="(" close=")">#{code}</foreach></select>

获取到部门相关信息之后,构建map结构,部门编码为key,部门信息为value

        List<KbDepartment> departments = sysUserMapper.listDepartmentsByCodes(tenantId, new ArrayList<>(allDeptCodes));Map<String, KbDepartment> departmentMap = departments.stream().collect(Collectors.toMap(KbDepartment::getCode, d -> d));
3. 递归补全所有部门信息编码需要使用编码查询部门信息
    /*** 递归添加父部门code*/private void addParentDepartments(String deptCode, Map<String, KbDepartment> departmentMap, Set<String> expandedDeptCodes) {KbDepartment dept = departmentMap.get(deptCode);if (dept != null && dept.getPid() != null && !"0".equals(dept.getPid()) && !expandedDeptCodes.contains(dept.getPid())) {expandedDeptCodes.add(dept.getPid());addParentDepartments(dept.getPid(), departmentMap, expandedDeptCodes);}}
4.根据完整部门编码获取完整部门信息
        // 再次查询所有部门信息(包含父部门)List<KbDepartment> allDepartments = sysUserMapper.listDepartmentsByCodes(tenantId, new ArrayList<>(expandedDeptCodes));Map<String, KbDepartment> allDepartmentMap = allDepartments.stream().collect(Collectors.toMap(KbDepartment::getCode, d -> d));
5.构建用户部门信息映射
// 由于一个用户会涉及多个组织假如,因此构建Map结构,如果k-v都是简单的String结构,会出现后面组织覆盖前面组织情况
Map<String, List<String>> userDeptFullPathMap = new HashMap<>();for (KbUserRoleInfo ud : userDepartments) {String fullPath = buildDepartmentFullPath(ud.getDepartmentNo(), allDepartmentMap);userDeptFullPathMap.computeIfAbsent(ud.getCode(), k -> new ArrayList<>()).add(fullPath);}/*** 递归构建部门完整路径字符串,格式:code#name,code#name,...*/private String buildDepartmentFullPath(String deptCode, Map<String, KbDepartment> departmentMap) {KbDepartment dept = departmentMap.get(deptCode);if (dept == null) {return "";}if ("0".equals(dept.getPid())) {return dept.getCode() + "#" + dept.getName();}String parentPath = buildDepartmentFullPath(dept.getPid(), departmentMap);return parentPath + "," + dept.getCode() + "#" + dept.getName();}
6.部门名称格式化
    /*** 重置部门名称*/public void resetDepartmentName() {// 处理部门名称String departmentName = this.getDepartmentName();// 部门名称从SQL数据库查询的规则是,部门编号#部门名称, 例如:0001#技术部,000101#开发一组// 这里将部门名称处理成为 技术部 > 开发一组,通过字符>连接起来if (StrUtil.isBlank(departmentName)) {return;}// 一个组织人员有多个部门的情况List<String> multipartDepartmentNameList = StrUtil.split(departmentName, "/");if (CollUtil.isEmpty(multipartDepartmentNameList)) {return;}List<String> departmentNames = new ArrayList<>();List<String> departmentShortNames = new ArrayList<>();List<String> departmentNos = new ArrayList<>();List<String> orgCodes = new ArrayList<>();for (String oneDepartmentName : multipartDepartmentNameList) {List<String> departmentNameList = StrUtil.split(oneDepartmentName, StrUtil.COMMA);// 获取一级的组织编号orgCodes.add(DepartmentUtils.getOrgCode(departmentNameList.get(0)));// 设置最后一个部门名称,获取departmentNameList的末尾元素String shortName = DepartmentUtils.splitDepartmentName(departmentNameList.get(departmentNameList.size() - 1));departmentShortNames.add(shortName);String sortNo = DepartmentUtils.splitDepartmentNo(departmentNameList.get(departmentNameList.size() - 1));departmentNos.add(sortNo);List<String> names = new LinkedList<>();for (String name : departmentNameList) {names.add(DepartmentUtils.splitDepartmentName(name));}departmentNames.add(StrUtil.join(" > ", names));}this.setOrgCode(StrUtil.join(StrUtil.COMMA, orgCodes));// 设置部门名称this.setDepartmentName(StrUtil.join(StrUtil.COMMA, departmentNames));this.setDepartmentNo(StrUtil.join(StrUtil.COMMA, departmentNos));this.setDepartmentShortName(StrUtil.join(StrUtil.COMMA, departmentShortNames));}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/84168.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/84168.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python初学者教程:如何从文本中提取IP地址

Python初学者教程:如何从文本中提取IP地址 在网络安全和数据分析领域,经常需要从文本文件中提取IP地址。本文将引导您使用Python创建一个简单但实用的工具,用于从文本文件提取所有IP地址并将其保存到新文件中。即使您是编程新手,也可以跟随本教程学习Python的基础知识! …

【Redis】Redis核心探秘:数据类型的编码实现与高速访问之道

&#x1f4da;️前言 &#x1f31f;&#x1f31f;&#x1f31f;精彩导读 本次我们将全面剖析Redis的核心技术要点&#xff0c;包括其丰富的数据类型体系、高效的编码方式以及秒级响应的性能奥秘。对于渴望深入理解Redis底层机制的技术爱好者&#xff0c;这是一次难得的学习机会…

Halcon —— 多种二维码检测

工业视觉实战&#xff1a;Halcon多类型二维码识别技术详解 在工业自动化场景中&#xff0c;兼容多种二维码类型是提高生产线灵活性的关键。本文将深入解析Halcon实现Data Matrix、QR Code和PDF417三种主流二维码的兼容识别方案&#xff0c;并重点解释核心算子参数。 一、多类型…

安卓vscodeAI开发实例

前言 前些天发现了一个巨牛的人工智能免费学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站 目录 一、安卓开发基础与工具链革新 1.1 Android Studio的局限性分析 1.2 VSCode在移动开发中的崛起 1.3 跨平台开发工具链对比…

③通用搜索---解析FastAdmin中的表格列表的功能

深度解析FastAdmin中的表格列表的功能-CSDN博客文章浏览阅读25次。本文将FastAdmin框架的CRUD功能配置要点进行了系统梳理。官方文档与开发经验相结合&#xff0c;详细介绍了菜单显示、TAB过滤、通用搜索、工具栏按钮、动态统计、快速搜索等17项功能的配置方法。包括字段渲染&a…

DeepSeek 助力 Vue3 开发:打造丝滑的日历(Calendar),日历_项目里程碑示例(CalendarView01_22)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…

Python爬虫实战:获取Diesel电商数据并分析

1. 引言 在当今数字化时代,电商平台积累了海量的产品和用户数据。通过对这些数据的挖掘和分析,企业可以深入了解市场动态、消费者需求和竞争态势,从而制定更有效的营销策略和产品规划。Diesel 作为知名的时尚品牌,其在电商平台上的表现备受关注。本研究旨在通过 Python 爬…

Spring RestTemplate + MultiValueMap vs OkHttp 多值参数的处理

&#x1f4cc; Spring RestTemplate vs OkHttp&#xff1a;多值参数处理 一、MultiValueMap 与 FormBody 的差异 特性RestTemplate MultiValueMapOkHttp FormBody多值参数支持✅ 原生支持&#xff08;add("key", "value") 自动追加&#xff09;❌ 需显…

GelSight视触觉3D轮廓仪赋能Beomni人形机器人触觉遥测,开启人形机器人触觉应用新场景

在智能制造、航空航天等领域&#xff0c;传统机器人常面临操作精度不足、环境适应力弱等问题。GelSight触觉传感技术与Beomni人形机器人的融合&#xff0c;为这些场景提供了新可能 —— 通过亚微米级触觉感知能力&#xff0c;操作员可远程感知物体表面细节&#xff0c;在复杂环…

python设置word的字体颜色

这个错误是由于python-docx的RGBColor对象没有.rgb属性导致的。正确的属性访问方式是分别获取红、绿(g)、蓝(b)三个分量。以下是修复方案&#xff1a; 错误原因分析 RGBColor对象的结构如下&#xff1a; from docx.shared import RGBColorcolor RGBColor(255, 204, 51) pri…

推荐模型之GBDT-LR

一、概念 GBDT-LR模型由FaceBook&#xff08;现在的Meta&#xff09;团队于2014年在论文《Practial Lessons from Predicting Clicks on Ads at Facebook》中提出&#xff0c;目标是用于预测FaceBook的广告点击量&#xff08;实际上广告和推荐领域很多算法模型都是共用的&#…

Java实现Excel图片URL筛选与大小检测

Java实现Excel图片URL筛选与大小检测 在数据处理场景中&#xff0c;我们常需筛选Excel中的图片URL。本文分享一个完整的Java方案&#xff0c;涵盖从读取图片URL到检测有效性、筛选大小&#xff0c;再到生成新Excel文件的全过程&#xff0c;同时讲解开发与优化过程&#xff0c;…

Java 实现后端调用 Chromium 浏览器无头模式截图的方案

Java 实现后端调用 Chromium 浏览器无头模式截图的方案 1. 使用 Playwright 优点&#xff1a;功能强大、支持多浏览器&#xff08;Chromium/Firefox/WebKit&#xff09;、支持异步操作。实现方式&#xff1a; 利用 Playwright 创建无头浏览器实例&#xff1b;使用 Java 的调度…

基于多模态文档解析与RAG的行业知识库构建技术指南

1. 技术背景 随着企业非结构化数据&#xff08;扫描件、PDF、图像等&#xff09;占比超过80%&#xff0c;传统关键词检索已无法满足精准问答需求。本文提出融合**计算机视觉&#xff08;CV&#xff09;与大语言模型&#xff08;LLM&#xff09;**的解决方案&#xff0c;关键技…

基于YOLOv11+PP-OCRv5深度学习的智能车牌检测与识别系统python源码+pytorch模型+评估指标曲线+精美GUI界面

【算法介绍】 智能车牌检测与识别系统借助当下前沿的 YOLOv11 算法以及 PP-OCRv5 算法&#xff0c;能够在复杂多样的环境场景中&#xff0c;快速且精准地达成实时车牌检测与识别任务。在现代交通管理领域&#xff0c;该技术意义重大&#xff0c;它能够推动涉及车辆识别与记录的…

[深度学习]全连接神经网络

目录 一、实验目的 二、实验环境 三、实验内容 3.1 完成解压数据集相关操作 3.2分析代码结构并运行代码查看结果 3.3修改超参数&#xff08;批量大小、学习率、Epoch&#xff09;并对比分析不同结果 3.4修改网络结构&#xff08;隐藏层数、神经元个数&#xff09;并对比分…

openEuler安装BenchmarkSQL

BenchmarkSQL是一个用于评估数据库性能的开源工具。它模拟TPC-C&#xff08;Transaction Processing Performance Council&#xff09;基准测试场景&#xff0c;该场景主要用于衡量数据库在处理大量并发事务时的能力。TPC-C测试场景模拟了一个典型的批发分销商的业务环境&#…

分库分表之优缺点分析

大家好&#xff0c;我是工藤学编程 &#x1f989;一个正在努力学习的小博主&#xff0c;期待你的关注实战代码系列最新文章&#x1f609;C实现图书管理系统&#xff08;Qt C GUI界面版&#xff09;SpringBoot实战系列&#x1f437;【SpringBoot实战系列】Sharding-Jdbc实现分库…

【2025年超详细】Git 系列笔记-4 git版本号及git相关指令运用。

系列笔记 【2025年超详细】Git 系列笔记-1 Git简述、Windows下git安装、Linux下git安装_displaying 2e144 commits. adjust this setting in -CSDN博客 【2025年超详细】Git 系列笔记-2 github连接超时问题解决_2025访问github-CSDN博客 【2025年超详细】Git 系列笔记-3 Git…

图像特征检测算法SuperPoint和SuperGlue

SuperPoint 背景与概述 &#xff1a;SuperPoint 是一个自监督的全卷积神经网络&#xff0c;用于提取图像中的兴趣点及其描述子。它在 2018 年由 Magic Leap 提出&#xff0c;通过在合成数据集上预训练一个基础检测器 MagicPoint&#xff0c;然后利用同胚适应技术对真实图像数据…