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
英文地址,請注明出處:http://en.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;然后利用同胚適應技術對真實圖像數據…