订阅更新

每个公司的薪水中位数:奇偶数一个公式搞定

SQL 实战 123 题 · 第 18 题 困难 约 2 分钟读完

LeetCode 569 · 中位数、ROW_NUMBER、窗口计数

本文目录
  1. 面试怎么回答
  2. 题意
  3. 表结构
  4. 思路
  5. 参考解法
  6. 易错点

面试怎么回答

我会用 ROW_NUMBER 按公司分区、薪水排序编号,再用 COUNT(*) OVER 拿每家公司人数,取编号在 FLOOR((cnt+1)/2) 和 FLOOR((cnt+2)/2) 之间的行,奇偶都能覆盖。要中位数的值就再对这几行求 AVG。

先把这段讲顺;面试官追问时,再展开下面的原理和细节。

详细讲解

题意

员工表有员工、公司和薪水,求每个公司薪水的中位数所在的员工记录(人数为偶数时返回中间两条)。

表结构

  • Employee:Id(主键)、Company、Salary

思路

按公司分区、薪水排序给每行编号,同时用窗口 COUNT 拿到公司人数 cnt。中位数的位置是 FLOOR((cnt+1)/2) 和 FLOOR((cnt+2)/2):奇数时两者相等,只取中间一条;偶数时正好是中间两条。

参考解法

select Id,Company,Salary
from (
select Id,Company,Salary,
ROW_NUMBER() over(partition by Company order by Salary) rk,
count(*) over(partition by Company) cnt
from Employee
)t1
where rk IN (FLOOR((cnt + 1)/2), FLOOR((cnt + 2)/2))

易错点

  • 用 RANK/DENSE_RANK 编号,薪水相同时编号重复,位置就对不上了,必须用 ROW_NUMBER。
  • 如果要的是中位数「值」,偶数时还要对中间两条求平均。
刷题进度保存在当前浏览器