在上篇文章基础上,我们进一步解决层级数据递归汇总问题 —— 让上级部门的统计结果自动包含所有下级部门数据(含多级子部门),并新增请假天数大于 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,后续用于孵…