569. 员工薪水中位数
写一个SQL查询,找出每个公司的工资中位数。
以 任意顺序 返回结果表。
查询结果格式如下所示。
SQL:方法一
select id, company, salary from (
select
id, company, salary,
row_number() over(partition by company order by salary) as rk,
count(id) over(partition by company) as total
from employee
) as t
where t.rk in (floor((total + 1) / 2), floor((total + 2) / 2));
解析
- 使用 row_number() 计算排名,并按照 company 分组, salary 升序
- 按照 company 分组,并计算总数
- 现在只需要筛选出中位数就可以了
- 筛选条件 floor((total + 1) / 2) 和 floor((total + 2) / 2) , floor 是想下取整
- 当 total = 6,中位数是 3 和 4 ,这里计算的结果正是 3 和 4
- 当 total = 5,中位数是 3,这里计算的两个值分别是 3 和 3
- 筛选条件也可以使用 where 排名 >= total / 2 and 排名 <= total / 2 + 1
- 当 total = 6,中位数是 3 和 4 , 排名 ≥ 3 and 排名 ≤ 4 ,筛选出来的是 3 和 4
- 当 total = 5,中位数是 3 , 排名 ≥ 2.5 and 排名 ≤ 3.5 ,筛选出来的就是 3
SQL:方法二
- 筛选条件 floor((total + 1) / 2) 和 floor((total + 2) / 2) , floor 是想下取整
SELECT Id, Company, Salary
FROM Employee
WHERE Id in (
SELECT e1.Id
FROM Employee e1
JOIN Employee e2
ON e1.Company = e2.Company
GROUP BY e1.Id
HAVING SUM(CASE WHEN e1.Salary >= e2.Salary THEN 1 ELSE 0 END) >= COUNT(*)/2
AND SUM(CASE WHEN e1.Salary <= e2.Salary THEN 1 ELSE 0 END) >= COUNT(*)/2
)
GROUP BY Company, Salary
ORDER BY Company
步骤:
- 做自连接,连接条件为公司名e1.Company = e2.Company,之后按e1.Id分组
- 两个子集的生成:
第一个子集:SUM(CASE WHEN e1.Salary >= e2.Salary THEN 1 ELSE 0 END) >= COUNT()/2 用来统计下半部分+1个
第二个子集:SUM(CASE WHEN e1.Salary <= e2.Salary THEN 1 ELSE 0 END) >= COUNT()/2用来统计上半部分+1个
这里取>= COUNT(*)/2是为了使两个子集有交集 - 接着把上面的两个条件求交集,作为HAVING子句的筛选条件,然后统计id
- 最后把选出来的id放到WHERE里面从Employee表找出对应的行即可
注意分组和排序