Oracle 遞歸 + Decode + 分組函數實現復雜樹形統計進階(第二課)

在上篇文章基礎上,我們進一步解決層級數據遞歸匯總問題 —— 讓上級部門的統計結果自動包含所有下級部門數據(含多級子部門),并新增請假天數大于 3 天的統計維度。通過遞歸 CTE、DECODE函數與分組函數的深度結合,實現真正意義上的樹形結構數據聚合。

一、業務需求升級:層級匯總與新增統計維度

核心目標

  1. 遞歸匯總:上級部門數據包含所有直屬 / 非直屬下級部門數據(如集團總部需匯總技術研發部、產品運營部及其子部門數據)
  2. 新增統計項:統計每個部門(含各級上級)的 "請假天數 > 3 天" 的記錄數
  3. 兼容原有指標:保留請假類型天數統計、狀態分類統計

數據模型擴展(無需修改表結構,新增計算邏輯)

-- 新增判斷邏輯:請假天數>3天標記DECODE(SIGN(leave_days - 3), 1, 1, 0) AS over_3_days_flag-- SIGN函數說明:返回1(正數)、0(零)、-1(負數),簡化條件判斷

二、關鍵技術升級:雙向遞歸 CTE 構建層級關系

1. 遞歸 CTE 重構:獲取每個部門的所有后代部門

WITH dept_ancestor AS (-- 初始層:每個部門自身作為祖先SELECTdept_id,dept_name,parent_dept_id,dept_id AS ancestor_id -- 核心字段:標記當前部門的頂層祖先FROM t_deptUNION ALL-- 遞歸層:向下遍歷子部門,繼承祖先IDSELECTd.dept_id,d.dept_name,d.parent_dept_id,da.ancestor_id -- 子部門繼承父部門的祖先IDFROM t_dept dJOIN dept_ancestor da ON d.parent_dept_id = da.dept_id)
  • 核心邏輯:為每個部門生成從自身到所有后代的層級路徑,ancestor_id表示當前統計的頂層部門(如子部門 4 的 ancestor_id 可為自身 4、父部門 2、根部門 1)
  • 遞歸方向:從父部門到子部門的向下遞歸,確保每個子部門關聯到所有上級祖先

2. 關聯請假表與遞歸 CTE

SELECTda.ancestor_id, -- 統計的目標部門(上級部門)da_dept.dept_name, -- 目標部門名稱tl.dept_id AS child_dept_id -- 實際產生數據的子部門ID(用于驗證層級)FROM dept_ancestor daLEFT JOIN t_dept da_dept ON da.ancestor_id = da_dept.dept_id -- 關聯祖先部門信息LEFT JOIN t_leave tl ON da.dept_id = tl.dept_id -- 關聯子部門請假數據-- 示例輸出:祖先部門1(集團總部)會關聯到子部門2、3、4、5的所有請假記錄

三、DECODE 函數進階:多維度條件聚合

1. 新增 "請假 > 3 天" 統計

SUM(DECODE(SIGN(tl.leave_days - 3), 1, 1, 0)) AS over_3_days_count-- 等價于:SUM(CASE WHEN tl.leave_days > 3 THEN 1 ELSE 0 END)-- DECODE優勢:通過數值比較簡化條件表達式,執行效率更高

2. 全維度統計表達式(整合新舊需求)

SELECTda_dept.dept_name AS 部門名稱,-- 請假類型統計(含下級部門)SUM(DECODE(tl.leave_type, '年假', tl.leave_days, 0)) AS 年假總天數,SUM(DECODE(tl.leave_type, '事假', tl.leave_days, 0)) AS 事假總天數,SUM(DECODE(tl.leave_type, '病假', tl.leave_days, 0)) AS 病假總天數,-- 狀態統計SUM(DECODE(tl.leave_status, '完成', 1, 0)) AS 完成請假數,SUM(DECODE(tl.leave_status, '進行中', 1, 0)) AS 進行中請假數,-- 新增統計:請假>3天SUM(DECODE(SIGN(tl.leave_days - 3), 1, 1, 0)) AS 超3天請假數

四、終極 SQL:遞歸匯總全層級數據

完整實現代碼如下:

相信我,如果你能學會下面這個SQL的寫法或者能看懂,那么你對ORACLE類似邏輯的處理已經達到極高的水平,這個SQL我認為有95%的人會看不懂。如果你們都會了歡迎留言打臉。因為這個SQL的實現我在7年前專門拿出來給全公司技術人員進行過培訓,留了一個類似的作業,結果1個完成的都沒有。你也可以考慮下,如果不用SQL來實現,而是讓你去通過代碼去實現這個需求的統計,你需要寫多少代碼來實現,需要多少時間?


WITH dept_ancestor AS (-- 構建部門層級關系,獲取每個部門的所有祖先路徑SELECTdept_id,dept_name,parent_dept_id,dept_id AS ancestor_id -- 初始祖先為自身FROM t_deptUNION ALL-- 遞歸向下遍歷子部門,繼承祖先IDSELECTd.dept_id,d.dept_name,d.parent_dept_id,da.ancestor_id -- 子部門的祖先與父部門一致FROM t_dept dJOIN dept_ancestor da ON d.parent_dept_id = da.dept_id),-- 提取祖先部門的基礎信息(避免重復計算)ancestor_info AS (SELECT DISTINCT ancestor_id, dept_nameFROM dept_ancestor)SELECTai.dept_name AS 部門名稱,-- 請假類型匯總(含所有子部門)SUM(DECODE(tl.leave_type, '年假', tl.leave_days, 0)) AS 年假總天數,SUM(DECODE(tl.leave_type, '事假', tl.leave_days, 0)) AS 事假總天數,SUM(DECODE(tl.leave_type, '病假', tl.leave_days, 0)) AS 病假總天數,-- 狀態匯總SUM(DECODE(tl.leave_status, '完成', 1, 0)) AS 完成請假數,SUM(DECODE(tl.leave_status, '進行中', 1, 0)) AS 進行中請假數,-- 新增統計項SUM(DECODE(SIGN(tl.leave_days - 3), 1, 1, 0)) AS 超3天請假數FROM ancestor_info aiLEFT JOIN dept_ancestor da ON ai.ancestor_id = da.ancestor_idLEFT JOIN t_leave tl ON da.dept_id = tl.dept_id -- 關聯子部門請假數據GROUP BY ai.ancestor_id, ai.dept_nameORDER BY ai.ancestor_id;

執行結果解析(新增示例數據后)

部門名稱

年假總天數

事假總天數

病假總天數

完成請假數

進行中請假數

超 3 天請假數

集團總部

8.5

2.0

3.0

2

3

2

技術研發部

4.5

2.0

0.0

1

2

2

產品運營部

1.5

0.0

3.0

1

1

0

后端開發組

3.5

0.0

0.0

1

1

1

前端開發組

0.0

2.0

0.0

0

1

1

核心邏輯拆解

1、遞歸 CTE 雙向關聯

????????向上:每個部門作為祖先,向下遍歷所有子部門(ancestor_id固定為頂層部門)

????????向下:通過da.dept_id = tl.dept_id關聯子部門的實際數據,確保上級部門能獲取所有下級數據

2、DECODE 的多維應用

????????類型統計:按leave_type分類累加天數

????????狀態統計:按leave_status分類計數

????????數值判斷:通過SIGN函數簡化 "大于 3 天" 的條件轉換

3、分組策略

????????按ancestor_id分組,確保每個上級部門匯總其所有后代(包括多級子部門)的數據

????????LEFT JOIN確保無數據部門(如根部門若自身無數據)仍能顯示統計結果

五、與上篇文章的核心區別

特性

上篇文章(單部門統計)

本文(遞歸層級統計)

統計范圍

僅當前部門或指定子部門

包含所有下級部門(多級遞歸)

遞歸方向

單向向下(固定根部門)

雙向關聯(每個部門可作為祖先)

核心字段

dept_id直接分組

ancestor_id遞歸分組

新增功能

請假天數 > 3 天統計、層級匯總

六、性能優化與注意事項

1. 索引優化建議

-- 為部門層級關系創建索引CREATE INDEX idx_dept_parent ON t_dept(parent_dept_id);-- 為請假表關聯字段創建索引CREATE INDEX idx_leave_dept ON t_leave(dept_id);

2. 大數據量處理

  • 若部門層級超過 1000 層,需調整 Oracle 遞歸限制:
ALTER SESSION SET MAX_RECURSION_DEPTH = 2000; -- 默認1000層

3. DECODE vs CASE WHEN 擴展

  • 復雜范圍判斷(如BETWEEN)建議用CASE WHEN,等值判斷優先用DECODE
  • 多層嵌套時注意DECODE的參數順序(嚴格按匹配順序執行)

七、總結:樹形數據統計的終極解決方案

通過遞歸 CTE 構建層級關系+DECODE 實現條件聚合+分組函數完成數據匯總,我們實現了:

????????1、真正的層級遞歸統計:上級部門自動包含所有下級數據,支持任意深度的組織架構

????????2、多維度復雜計算:在單個 SQL 中完成類型統計、狀態分類、數值判斷等多重邏輯

????????3、代碼極簡主義:相比傳統 Java 遞歸 + 多層循環,SQL 代碼量減少 90% 以上,且執行效率更高

????????這種方案特別適合組織架構復雜、層級統計頻繁的企業級應用(如人力資源管理、財務成本分攤等場景)。掌握遞歸與DECODE的組合使用,能讓你在處理樹形數據時如虎添翼,真正發揮 Oracle 數據庫的原生優勢。如果你能學會這種SQL邏輯,相信我,肯定會對你在實際工作中有巨大幫助。歡迎關注留言,期待與您一起進步。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/912292.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/912292.shtml
英文地址,請注明出處:http://en.pswp.cn/news/912292.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MySQL 數據類型全面指南:詳細說明與關鍵注意事項

MySQL 數據類型全面指南:詳細說明與關鍵注意事項 MySQL 提供了豐富的數據類型,合理選擇對數據庫性能、存儲效率和數據準確性至關重要。以下是所有數據類型的詳細說明及使用注意事項: 一、數值類型 整數類型 類型字節有符號范圍無符號范圍說…

leetcode437-路徑總和III

leetcode 437 思路 利用前綴和hash map解答 前綴和在這里的含義是:從根節點到當前節點的路徑上所有節點值的總和 我們使用一個 Map 數據結構來記錄這些前綴和及其出現的次數 具體思路如下: 初始化:創建一個 Map ,并將前綴和 …

UI前端與數字孿生融合探索新領域:智慧家居的可視化設計與實現

hello寶子們...我們是艾斯視覺擅長ui設計、前端開發、數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩! 一、引言:智慧家居的數字化轉型浪潮 在物聯網與人工智能技術的推動下&#xff0c…

數據結構知識點總結--緒論

1.1 數據結構的基本概念 1.1.1 基本概念和術語 主要涉及概念有: 數據、數據元素、數據對象、數據類型、數據結構 #mermaid-svg-uyyvX6J6ofC9rFSB {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-uyyvX6…

pip install mathutils 安裝 Blender 的 mathutils 模塊時,編譯失敗了

你遇到的問題是因為你試圖通過 pip install mathutils 安裝 Blender 的 mathutils 模塊時,編譯失敗了,主要原因是: 2018年 的老版本也不行 pip install mathutils2.79 ? 報錯核心總結: 缺失頭文件 BLI_path_util.h:…

編譯安裝交叉工具鏈 riscv-gnu-toolchain

參考鏈接: https://zhuanlan.zhihu.com/p/258394849 1,下載源碼 git clone https://gitee.com/mirrors/riscv-gnu-toolchain 2,進入目錄 cd riscv-gnu-toolchain 3,去掉qemu git rm qemu 4,初始化 git submodule…

復制 生成二維碼

一、安裝插件 1、復制 npm install -g copy-to-clipboard import copy from copy-to-clipboard; 2、生成二維碼 & 下載 npm install -g qrcode import QRCode from qrcode.react; 二、功能:生成二維碼 & 下載 效果圖 1、常規使用(下載圖片模糊…

自由職業的經營視角

“領導力的核心是幫助他人看到自己看不到的東西。” — 彼得圣吉 最近與一些自由職業者的交流中,發現很多專業人士都會從專業視角來做交流,這也讓我更加理解我們海外戰略顧問莊老師在每月輔導時的提醒——經營者視角和專業人士視角的不同。這不僅讓大家獲…

MR30分布式 IO在物流堆垛機的應用

在現代物流行業蓬勃發展的浪潮中,物流堆垛機作為自動化倉儲系統的核心設備,承擔著貨物的高效存取與搬運任務。它憑借自動化操作、高精度定位等優勢,極大地提升了倉儲空間利用率和貨物周轉效率。然而,隨著物流行業的高速發展&#…

告別固定密鑰!在單一賬戶下用 Cognito 實現 AWS CLI 的 MFA 單點登錄

大家好,很多朋友,特別是通過合作伙伴或服務商使用 AWS 的同學,可能會發現自己的 IAM Identity Center 功能受限,無法像在組織管理賬戶里那樣輕松配置 CLI 的 SSO (aws configure sso)。那么,我們就要放棄治療&#xff…

未來機器視覺軟件將更注重成本控制,邊緣性能,魯棒性、多平臺支持、模塊優化與性能提升,最新版本opencv-4.11.0更新了什么

OpenCV 4.11.0 作為 4.10.0 的后續版本,雖然沒有在提供的搜索結果中直接列出詳細更新內容,但結合 OpenCV 4.10.0 的重大改進方向(發布于 2024 年 6 月),可以合理推斷 4.11.0 版本可能延續了對多平臺支持、模塊優化和性能提升的強化。以下是基于 OpenCV 近期更新模式的推測…

小程序入門:數據請求全解析

在微信小程序開發中,數據請求是實現豐富功能的關鍵環節。本文將帶你深入了解小程序數據請求的相關知識,包括請求限制、配置方法以及不同請求方式的實現,還會介紹如何在頁面加載時自動請求數據,同時附上詳細代碼示例,讓…

開源版gpt4o 多模態MiniGPT-4 實現原理詳解

MiniGPT-4是開源的GPT-4的平民版。本文用帶你快速掌握多模態大模型MiniGPT-4的模型架構、訓練秘訣、實戰亮點與改進方向。 1 模型架構全景:三層協同 📊 模型底部實際輸入圖像,經 ViT Q-Former 編碼。藍色方塊 (視覺編碼器):左側…

Flutter基礎(控制器)

第1步:找個遙控器(創建控制器)? // 就像買新遙控器要裝電池 TextEditingController myController TextEditingController(); ??第2步:連上你的玩具(綁定到組件)?? TextField(controller: myContro…

Spring Boot使用Redis常用場景

Spring Boot使用Redis常用場景 一、概述:Redis 是什么?為什么要用它? Redis(Remote Dictionary Server)是一個內存中的數據存儲系統(類似一個“超級大字典”),它能存各種類型的數據…

CAD文件處理控件Aspose.CAD教程:在 C# 中將 DXF 文件轉換為 SVG - AutoCAD C# 示例

概述 使用 C# 輕松將DXF文件轉換為SVG。此轉換可更好地兼容 Web 應用程序,并增強 CAD 圖紙的視覺呈現效果。使用Aspose.CAD for .NET ,開發人員可以輕松實現此轉換過程。該 SDK 提供強大的功能,使其成為 C# 開發人員的可靠選擇。Aspose.CAD …

Gitee 持續集成與交付(CI/CD)篇

Gitee 持續集成與交付(CI/CD)篇 🚀 文章目錄 Gitee 持續集成與交付(CI/CD)篇 🚀🎯 什么是 CI/CD?🌟 Gitee Go 介紹? 核心特性🎨 支持的技術棧 🚀…

深度學習:PyTorch卷積神經網絡圖像分類案例分享

本文目錄: 一、了解CIFAR-10數據集二、案例之導包三、案例之創建數據集四、案例之搭建神經網絡(模型構建)五、案例之編寫訓練函數(訓練模型)六、案例之編寫預測函數(模型測試) 前言:…

記錄多功能按鍵第二種寫法使用定時器周期間隔判斷.

邏輯是通過定時器溢出周期進行判斷按下次數 比如設置定時器溢出周期為500MS,每次溢出都會判斷按鍵按下次數,如果下個周期前沒有觸發按下,則結束鍵值判斷.并確定觸發鍵值.清空按下次數標志.測試比一個定時器周期按下按鍵次數判斷寫法要穩定... 記錄STM32實現多功能按鍵_stm32一…

【安卓Sensor框架-1】SensorService 的啟動流程

內核啟動后,首個用戶空間進程init(pid1)解析init.rc配置文件,啟動關鍵服務(如Zygote和ServiceManager)。 Zygote服務配置為/system/bin/app_process --zygote --start-system-server,后續用于孵…