Oracle HR 模式递归函数练习(基于 employees 表)

Oracle 中递归查询 核心用 CONNECT BY 语法(专用于树形结构查询),employees 表是完美的练习素材:

  • 字段:employee_id(员工 ID)、first_name||last_name(员工姓名)、manager_id(上级 ID)
  • 关系:manager_id 关联 employee_id,形成上下级树形层级(总裁→总监→经理→普通员工)

先确认表结构(HR 用户默认表):

复制代码
-- 查看 employees 表核心字段
SELECT employee_id, last_name, manager_id, job_id 
FROM employees;

下面给你5 个由浅入深的递归练习示例,直接复制运行即可。


练习 1:基础递归 - 查询所有员工的上下级层级(从总裁到基层)

需求:展示每个员工的层级、姓名、上级 ID,从最高级(总裁,manager_id 为 NULL)开始递归。

复制代码
SELECT
  -- LEVEL 是Oracle伪列,代表递归层级(根节点=1)
  LEVEL AS 层级,
  employee_id AS 员工ID,
  last_name AS 员工姓名,
  manager_id AS 上级ID
FROM employees
-- 递归条件:上级ID = 员工ID(父子关联)
CONNECT BY PRIOR employee_id = manager_id
-- 根节点:总裁(没有上级,manager_id IS NULL)
START WITH manager_id IS NULL
-- 排序:按层级、员工ID排序
ORDER SIBLINGS BY employee_id;

✅ 核心语法:

  • START WITH:指定递归根节点(起始行)
  • CONNECT BY PRIOR:指定父子关联关系
  • LEVEL:自动生成递归层级

练习 2:反向递归 - 从指定员工向上查所有上级(溯源)

需求:查询员工「Whalen」(employee_id=200)的所有上级,直到总裁。

复制代码
SELECT
  LEVEL AS 溯源层级,
  employee_id,
  last_name,
  manager_id
FROM employees
-- 反向递归:PRIOR 放在 manager_id(子查父)
CONNECT BY PRIOR manager_id = employee_id
-- 起始节点:指定员工 Whalen
START WITH employee_id = 200;

✅ 关键点:递归方向

  • 向下查下级:PRIOR employee_id = manager_id
  • 向上查上级:PRIOR manager_id = employee_id

练习 3:递归 + 函数 - 拼接员工的完整上级链

需求 :给每个员工生成完整上级路径 (如:King→Kochhar→Whalen),用 SYS_CONNECT_BY_PATH 递归拼接。

复制代码
SELECT
  employee_id AS 员工ID,
  last_name AS 员工姓名,
  -- 递归拼接路径,分隔符用 →
  SYS_CONNECT_BY_PATH(last_name, '→') AS 完整上级链
FROM employees
CONNECT BY PRIOR employee_id = manager_id
START WITH manager_id IS NULL
ORDER SIBLINGS BY employee_id;

✅ 高阶函数:SYS_CONNECT_BY_PATH(列名, 分隔符) → 自动生成树形路径


练习 4:递归过滤 - 只查询指定层级的员工

需求 :查询第 2 层级(总裁的直接下属)所有员工。

复制代码
SELECT
  LEVEL AS 层级,
  employee_id,
  last_name,
  job_id
FROM employees
WHERE LEVEL = 2  -- 过滤递归层级
CONNECT BY PRIOR employee_id = manager_id
START WITH manager_id IS NULL
ORDER BY employee_id;

✅ 技巧:WHERE LEVEL = 数字 精准筛选递归层级


练习 5:递归统计 - 每个上级的下属总人数

需求 :统计每个管理者直接 + 间接下属的总数量(递归计数)。

复制代码
SELECT
  e.employee_id AS 管理者ID,
  e.last_name AS 管理者姓名,
  -- 子查询递归统计下属总数
  (SELECT COUNT(*) FROM employees 
   CONNECT BY PRIOR employee_id = manager_id
   START WITH manager_id = e.employee_id) AS 下属总人数
FROM employees e
-- 只展示有下属的管理者
WHERE EXISTS (SELECT 1 FROM employees WHERE manager_id = e.employee_id)
ORDER BY 下属总人数 DESC;

✅ 进阶用法:递归查询嵌套在统计函数中,实现树形计数


练习 6:WITH 递归子句(11gR2+ 通用递归语法)

Oracle 11gR2 开始支持 ANSI 标准递归 WITH,兼容其他数据库(MySQL/PostgreSQL),推荐掌握:

复制代码
-- 递归CTE查询员工层级
WITH emp_tree(员工ID, 姓名, 上级ID, 层级) AS (
  -- 锚点成员(根节点:总裁)
  SELECT employee_id, last_name, manager_id, 1
  FROM employees
  WHERE manager_id IS NULL
  UNION ALL
  -- 递归成员(连接子节点)
  SELECT e.employee_id, e.last_name, e.manager_id, et.层级 + 1
  FROM employees e
  JOIN emp_tree et ON e.manager_id = et.员工ID
)
SELECT * FROM emp_tree
ORDER BY 层级, 员工ID;

总结

  1. 核心语法 :START WITH(根节点)+ CONNECT BY PRIOR(父子关系)
  2. 方向判断 :
    • 向下查下级:PRIOR 员工ID = 上级ID
    • 向上查上级:PRIOR 上级ID = 员工ID
  3. 实用函数 :LEVEL(层级)、SYS_CONNECT_BY_PATH(路径拼接)
  4. employees 表是学习 Oracle 递归的最佳案例,吃透这 5 个例子就能掌握 90% 递归场景
相关推荐
数据库急诊室_阿哲2 小时前
一次加索引建议的复核记录:从报告到签字
数据库·ai数据库
青瓦梦滋3 小时前
Redis主从复制
服务器·数据库·redis·缓存·bootstrap
慧都小妮子4 小时前
Wyn商业智能国产数据库适配:数据接入、分析缓存与审计日志验证清单
数据库·数据分析·数据可视化·审计日志·商业智能
Joy T5 小时前
Redis Lua 原子限流:Lua 脚本、竞态条件与并发控制
数据库·redis·lua·限流·竞态条件·redis scripting
杨凯凡5 小时前
MySQL 死锁怎么排查?InnoDB 锁等待与 Spring Boot 整事务重试实战
数据库·spring boot·mysql
Aloudata5 小时前
Claude 做数据分析的这两年:一份复盘与发展线索
大数据·数据库·人工智能·数据挖掘·数据分析·dataagent
Decay__5 小时前
01_SQLServer 体系架构全解 —— 实例进程、关系引擎、SQLOS 与事务日志深入
运维·数据库·sql·mysql·架构
zhanghaha13146 小时前
C# 系列教程_12 字符串 string 保姆级系统教程(面向新手,大量示例 + 原理讲解)
开发语言·数据库·c#
韩曙亮6 小时前
【错误记录】安卓 adb 调试 5037 端口占用排查 ( adb 的三层结构 | 找出本机占用 5037 的进程 )
android·数据库·adb·安卓·错误记录
瑞雪兆丰年兮6 小时前
JavaWeb-day07-MySQL(DQL&多表设计)
java·开发语言·数据库·sql·mysql·javaweb·web