SQL-leetcode—3482. 分析组织层级

3482. 分析组织层级

表:Employees

±---------------±--------+

| Column Name | Type |

±---------------±--------+

| employee_id | int |

| employee_name | varchar |

| manager_id | int |

| salary | int |

| department | varchar |

±---------------±---------+

employee_id 是这张表的唯一主键。

每一行包含关于一名员工的信息,包括他们的 ID,姓名,他们经理的 ID,薪水和部门。

顶级经理(CEO)的 manager_id 是空的。

编写一个解决方案来分析组织层级并回答下列问题:

层级:对于每名员工,确定他们在组织中的层级(CEO 层级为 1,CEO 的直接下属员工层级为 2,以此类推)。

团队大小:对于每个是经理的员工,计算他们手下的(直接或间接下属)总员工数。

薪资预算:对于每个经理,计算他们控制的总薪资预算(所有手下员工的工资总和,包括间接下属,加上自己的工资)。

返回结果表以 层级 升序 排序,然后以预算 降序 排序,最后以 employee_name 升序 排序。

结果格式如下所示。

示例:

输入:

Employees 表:

±------------±--------------±-----------±-------±------------+

| employee_id | employee_name | manager_id | salary | department |

±------------±--------------±-----------±-------±------------+

| 1 | Alice | null | 12000 | Executive |

| 2 | Bob | 1 | 10000 | Sales |

| 3 | Charlie | 1 | 10000 | Engineering |

| 4 | David | 2 | 7500 | Sales |

| 5 | Eva | 2 | 7500 | Sales |

| 6 | Frank | 3 | 9000 | Engineering |

| 7 | Grace | 3 | 8500 | Engineering |

| 8 | Hank | 4 | 6000 | Sales |

| 9 | Ivy | 6 | 7000 | Engineering |

| 10 | Judy | 6 | 7000 | Engineering |

±------------±--------------±-----------±-------±------------+

输出:

±------------±--------------±------±----------±-------+

| employee_id | employee_name | level | team_size | budget |

±------------±--------------±------±----------±-------+

| 1 | Alice | 1 | 9 | 84500 |

| 3 | Charlie | 2 | 4 | 41500 |

| 2 | Bob | 2 | 3 | 31000 |

| 6 | Frank | 3 | 2 | 23000 |

| 4 | David | 3 | 1 | 13500 |

| 7 | Grace | 3 | 0 | 8500 |

| 5 | Eva | 3 | 0 | 7500 |

| 9 | Ivy | 4 | 0 | 7000 |

| 10 | Judy | 4 | 0 | 7000 |

| 8 | Hank | 4 | 0 | 6000 |

±------------±--------------±------±----------±-------+

解释:

组织结构:

Alice(ID:1)是 CEO(层级 1)没有经理。

Bob(ID:2)和 Charlie(ID:3)是 Alice 的直接下属(层级 2)

David(ID:4),Eva(ID:5)从属于 Bob,而 Frank(ID:6)和 Grace(ID:7)从属于 Charlie(层级 3)

Hank(ID:8)从属于 David,而 Ivy(ID:9)和 Judy(ID:10)从属于 Frank(层级 4)

层级计算:

CEO(Alice)层级为 1

每个后续的管理层级都会使层级数加 1

团队大小计算:

Alice 手下有 9 个员工(除她以外的整个公司)

Bob 手下有 3 个员工(David,Eva 和 Hank)

Charlie 手下有 4 个员工(Frank,Grace,Ivy 和 Judy)

David 手下有 1 个员工(Hank)

Frank 手下有 2 个员工(Ivy 和 Judy)

Eva,Grace,Hank,Ivy 和 Judy 没有直接下属(team_size = 0)

预算计算:

Alice 的预算:她的工资(12000)+ 所有员工的工资(72500)= 84500

Charlie 的预算:他的工资(10000)+ Frank 的预算(23000)+ Grace 的工资(8500)= 41500

Bob 的预算:他的工资 (10000) + David 的预算(13500)+ Eva 的工资(7500)= 31000

Frank 的预算:他的工资 (9000) + Ivy 的工资(7000)+ Judy 的工资(7000)= 23000

David 的预算:他的工资 (7500) + Hank 的工资(6000)= 13500

没有直接下属的员工的预算等于他们自己的工资。

注意:

结果先以层级升序排序

在同一层级内,员工按预算降序排序,然后按姓名升序排序

题解

本质是在一张"员工-经理"表上,按树形层级做两类统计:

层级:CEO 为根结点,CEO 层级=1,往下每多一层+1。

团队大小:以某员工为根的子树大小减 1(不算自己),即所有直接/间接下属人数。

薪资预算:该员工整棵子树里所有员工工资之和(包括自己)。

方法一

复制代码
-- 算每个人的层级(从 CEO 向下)
WITH RECURSIVE level_cte AS (
    -- CEO(顶层经理)
    SELECT 
        employee_id,
        manager_id,
        1 AS level
    FROM Employees
    WHERE manager_id IS NULL

    UNION ALL

    -- 其余员工:层级 = 上级层级 + 1
    SELECT 
        e.employee_id,
        e.manager_id,
        lc.level + 1 AS level
    FROM Employees e
    JOIN level_cte lc 
      ON e.manager_id = lc.employee_id
),
-- 2. 生成所有"经理-下属"对(传递闭包),包括自己
hierarchy AS (
    -- 每个人都是自己的"下属"(为了把自己也算进预算里)
    SELECT 
        employee_id AS manager_id,
        employee_id AS subordinate_id
    FROM Employees

    UNION ALL

    -- 递归往下扩展:当前 subordinate 的直接下属
    SELECT 
        h.manager_id,
        e.employee_id AS subordinate_id
    FROM hierarchy h
    JOIN Employees e 
      ON e.manager_id = h.subordinate_id
),
-- 3. 在层级结构上聚合团队大小和预算
agg AS (
    SELECT 
        h.manager_id,
        COUNT(*) - 1 AS team_size,      -- 减去自己
        SUM(e.salary) AS budget         -- 包含自己
    FROM hierarchy h
    JOIN Employees e 
      ON h.subordinate_id = e.employee_id
    GROUP BY h.manager_id
)
SELECT 
    e.employee_id,
    e.employee_name,
    lc.level,
    COALESCE(a.team_size, 0) AS team_size,
    COALESCE(a.budget, e.salary) AS budget
FROM Employees e
JOIN level_cte lc 
  ON e.employee_id = lc.employee_id
LEFT JOIN agg a 
  ON e.employee_id = a.manager_id
ORDER BY 
    lc.level ASC,
    budget DESC,
    e.employee_name ASC;

思路:

level_cte 只负责从 CEO 开始一路向下,把每个人的层级算出来;

hierarchy 把"经理-下属"的传递关系全部展开(一个经理对应所有直接/间接下属),包括自己;

agg 在这个展开表上聚合出团队人数(COUNT-1)和预算(SUM),再与员工和层级表关联;

最后按题目要求:先按层级升序,再按预算降序,最后按员工姓名升序排序。

相关推荐
Flynt11 小时前
Room 3.0 包名重构 + KMP 迁移:我把项目升级踩了个遍
android·数据库·kotlin
澈20711 小时前
QT入门第十一天:数据库编程(上)SQLite入门与增删改查 | 零基础学QT
数据库·qt·sqlite
想吃火锅100512 小时前
【leetcode】146.LRU缓存js
算法·leetcode·缓存
这个DBA有点耶1 天前
NULL不是空——数据库里最反直觉的设计,90%新人踩过的坑
数据库·mysql·代码规范
这个DBA有点耶1 天前
AI写的SQL跑崩了生产库,这锅谁背?
数据库·人工智能·程序员
镜舟科技1 天前
Databricks 再提 LTAP,AI 时代的数据底座为何重回大一统叙事?
数据库·架构·agent
Databend1 天前
从湖仓升级为 Agent 时代的数据控制面,Snowflake 和 Databricks 有哪些布局
大数据·数据库·agent
ClouGence1 天前
SQL Server CDC 能放到 Always On 备库读吗?一文讲透原理与实践
数据库·sql server
先吃饱再说2 天前
存储的进化:从 MySQL 到浏览器缓存,数据到底住在哪?
数据库
Nturmoils2 天前
字段太多看不全,ksql 的展开模式和输出控制怎么用
数据库·后端