【LeetCode-SQL】569. 员工薪水中位数
目录
- 一、题目
- 二、解决
- 1、窗口函数
- 2、自关联后分组筛选
- 三、参考
一、题目
表: Employee
+--------------+---------+
| Column Name | Type |
+--------------+---------+
| id | int |
| company | varchar |
| salary | int |
+--------------+---------+
Id是该表的主键列。
该表的每一行表示公司和一名员工的工资。
写一个SQL查询,找出每个公司的工资中位数。
以 任意顺序 返回结果表。
查询结果格式如下所示。
示例 1:
输入:
Employee 表:
+----+---------+--------+
| id | company | salary |
+----+---------+--------+
| 1 | A | 2341 |
| 2 | A | 341 |
| 3 | A | 15 |
| 4 | A | 15314 |
| 5 | A | 451 |
| 6 | A | 513 |
| 7 | B | 15 |
| 8 | B | 13 |
| 9 | B | 1154 |
| 10 | B | 1345 |
| 11 | B | 1221 |
| 12 | B | 234 |
| 13 | C | 2345 |
| 14 | C | 2645 |
| 15 | C | 2645 |
| 16 | C | 2652 |
| 17 | C | 65 |
+----+---------+--------+
输出:
+----+---------+--------+
| id | company | salary |
+----+---------+--------+
| 5 | A | 451 |
| 6 | A | 513 |
| 12 | B | 234 |
| 9 | B | 1154 |
| 14 | C | 2645 |
+----+---------+--------+
进阶: 你能在不使用任何内置函数或窗口函数的情况下解决它吗?
二、解决
1、窗口函数
思路:
S1:使用 row_number() 计算排名,并按照 company 分组并计算总数
S2:筛选出中位数,条件 floor((total + 1) / 2)
和 floor((total + 2) / 2)
。
- 当 total = 6,中位数是 3 和 4 ,这里计算的结果正是 3 和 4
- 当 total = 5,中位数是 3,这里计算的两个值分别是 3 和 3
代码-版本1:
# 超 98%
SELECTId AS id,Company AS company,Salary AS salary
FROM(SELECTId,Company,Salary,COUNT(*) OVER(PARTITION BY Company) AS cnt,ROW_NUMBER() OVER(PARTITION BY Company ORDER BY Salary, Id) AS ranking1,ROW_NUMBER() OVER(PARTITION BY Company ORDER BY Salary DESC, Id DESC) AS ranking2FROMEmployee) t1
WHEREROUND(cnt / 2, 0) <= ranking1
ANDROUND(cnt / 2, 0) <= ranking2
ORDER BYCompany,Salary,Id;
补充:中位数代码实现部分解释
ROUND(cnt / 2, 0) <= ranking1
ANDROUND(cnt / 2, 0) <= ranking2
代码-版本2:
# 超5%
select id, company, salary from (selectid, company, salary,row_number() over(partition by company order by salary) as 排名,count(id) over(partition by company) as totalfrom employee
) as temp
where temp.排名 in (floor((total + 1) / 2), floor((total + 2) / 2));
# where 排名 >= total / 2 and 排名 <= total / 2 + 1
2、自关联后分组筛选
思路:
将每个人和公司的其他所有人一一比较,将 employee 通过 company 自连,并且按照 e2.company 和 e2.salary 进行分组。
代码-版本1:
# 超5%
select t1.Id as id, t1.Company as company, t1.Salary as salary
from Employee t2, Employee t1 # t2在前
where t1.Company = t2.Company
group by t1.Company, t1.Salary
having sum(case when t1.Salary = t2.Salary then 1 else 0 end) # 自己和自己比较的个数>= abs( sum( sign(t1.Salary - t2.Salary) ) ) # 大于自己个数 与 小于自己个数 的差值
order by t1.Company asc, t1.Salary asc, t1.Id asc;
理解:
# 核心代码:
sum(case when t1.Salary = t2.Salary then 1 else 0 end) # 自己和自己比较的个数
>=
abs( sum( sign(t1.Salary - t2.Salary) ) ) # 大于自己个数 与 小于自己个数 的差值
abs(sum(sign(e1.salary - e2.salary)))
,sign()
可以确定一个数是正数、负数或零,以 A 、C公司为例。
- A公司:一般,偶数情况下中位数的差值
abs(sum(sign(e1.salary-e2.salary)))
为1,距离越远,差值越大。
e1.salary | e2.salary | sign(e1.salary-e2.salary) 结果 | case when t1.Salary = t2.Salary then 1 else 0 end |
---|---|---|---|
15 | 15 | 0 | 1 |
341 | 15 | 1 | 0 |
451 | 15 | 1 | 0 |
513 | 15 | 1 | 0 |
2341 | 15 | 1 | 0 |
15314 | 15 | 1 | 0 |
- | - | abs(sum(*))=5 | abs(sum(*))=1 |
- | - | - | - |
15 | 341 | -1 | 0 |
341 | 341 | 0 | 1 |
451 | 341 | 1 | 0 |
513 | 341 | 1 | 0 |
2341 | 341 | 1 | 0 |
15314 | 341 | 1 | 0 |
- | - | abs(sum(*))=3 | abs(sum(*))=1 |
- | - | - | - |
15 | 451 | -1 | 0 |
341 | 451 | -1 | 0 |
451 | 451 | 0 | 1 |
513 | 451 | 1 | 0 |
2341 | 451 | 1 | 1 |
15314 | 451 | 1 | 0 |
- | - | abs(sum(*))=1 | abs(sum(*))=1 |
- | - | - | - |
15 | 513 | -1 | 0 |
341 | 513 | -1 | 0 |
451 | 513 | -1 | 0 |
513 | 513 | 0 | 1 |
2341 | 513 | 1 | 0 |
15314 | 513 | 1 | 0 |
- | - | abs(sum(*))=1 | abs(sum(*))=1 |
- | - | - | - |
15 | 2341 | -1 | 0 |
341 | 2341 | -1 | 0 |
451 | 2341 | -1 | 0 |
513 | 2341 | -1 | 0 |
2341 | 2341 | 0 | 1 |
15314 | 2341 | 1 | 0 |
- | - | abs(sum(*))=3 | abs(sum(*))=1 |
- | - | - | - |
15 | 15314 | -1 | 0 |
341 | 15314 | -1 | 0 |
451 | 15314 | -1 | 0 |
513 | 15314 | -1 | 0 |
2341 | 15314 | -1 | 0 |
15314 | 15314 | 0 | 1 |
- | - | abs(sum(*))=5 | abs(sum(*))=1 |
- | - | - | - |
- B公司(
删除| 7 | B | 15 |
):一般,奇数情况下中位数的差值abs(sum(sign(e1.salary-e2.salary)))
为0,距离越远,差值越大。
e1.salary | e2.salary | sum(abs(sign(e1.salary-e2.salary))) | case when t1.Salary = t2.Salary then 1 else 0 end |
---|---|---|---|
13 | … | -4 | 1 |
234 | … | -2 | 1 |
1154 | … | 0 | 1 |
1221 | … | 2 | 1 |
1345 | … | 4 | 1 |
- C公司:中位数重复情况,相同中位数个数增加,其他不变。
e1.salary | e2.salary | sign(e1.salary-e2.salary) 结果 | case when t1.Salary = t2.Salary then 1 else 0 end |
---|---|---|---|
65 | 65 | 0 | 1 |
2345 | 65 | 1 | 0 |
2645 | 65 | 1 | 0 |
2645 | 65 | 1 | 0 |
2652 | 65 | 1 | 0 |
- | - |
abs(sum(*))=4
|
abs(sum(*))=1 |
- | - | - | - |
65 | 2345 | -1 | 0 |
2345 | 2345 | 0 | 1 |
2645 | 2345 | 1 | 0 |
2645 | 2345 | 1 | 0 |
2652 | 2345 | 1 | 0 |
- | - |
abs(sum(*))=2
|
abs(sum(*))=1 |
- | - | - | - |
65 | 2645 | -1 | 0 |
2345 | 2645 | -1 | 0 |
2645 | 2645 | 0 | 1 |
2645 | 2645 | 0 | 1 |
2652 | 2645 | 1 | 0 |
- | - |
abs(sum(*))=1
|
abs(sum(*))=2 |
- | - | - | - |
65 | 2645 | -1 | 0 |
2345 | 2645 | -1 | 0 |
2645 | 2645 | 0 | 1 |
2645 | 2645 | 0 | 1 |
2652 | 2645 | 1 | 0 |
- | - |
abs(sum(*))=1
|
abs(sum(*))=2 |
- | - | - | - |
65 | 2652 | -1 | 0 |
2345 | 2652 | -1 | 0 |
2645 | 2652 | -1 | 0 |
2645 | 2652 | -1 | 0 |
2652 | 2652 | 0 | 1 |
- | - |
abs(sum(*))=4
|
abs(sum(*))=1 |
- | - | - | - |
可以通过下面的SQL对上面的结果进行验证:
selecte1.id as e1_id,e1.company as e1_company,e1.salary as e1_salary,e2.id as e2_id,e2.company as e2_company,e2.salary as e2_salary,sum(case when e1.salary = e2.salary then 1 else 0 end) as selfCnt, # 自己和自己比较的个数sum(sign(e1.salary - e2.salary)) as moreSubLess # 大于自己个数 与 小于自己个数 的差值
from employee e1 left join employee e2 using(company)
group by e1.company, e1.salary
order by e1.id;
# 可略 - any_value():选择被分到同一组的数据里第一条数据的指定列值作为返回数据。
selectsum(case when e1.salary = e2.salary then 1 else 0 end),sum(sign(e1.salary - e2.salary)),any_value(e1.id) as id
from employee e1 left join employee e2 using(company)
group by e1.company, e1.salary
order by id;
三、参考
1、四种方法解员工薪水中位数
2、简洁窗口函数排序
3、MySQL + 开窗函数
4、any_value()函数
【LeetCode-SQL】569. 员工薪水中位数相关推荐
- LeetCode MySQL 569. 员工薪水中位数(over窗口函数)
文章目录 1. 题目 2. 解题 1. 题目 Employee 表包含所有员工.Employee 表有三列:员工Id,公司名和薪水. +-----+------------+--------+ |Id ...
- 【每日SQL打卡】DAY 4丨员工薪水中位数【难度困难】
活动介绍: 「数据仓库技术交流群」已经正式启动每日SQL打卡,帮助大家扎实基础,努力工作之余,别忘了自我提升. 欢迎报名和邀请小伙伴参与,一个人可能走得很快,但一群人会走得很远.
- [SQL实战]之获取所有部门中当前员工薪水最高的相关信息
题目描述 获取所有部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary CREATE TABLE dept_emp ( emp_no int(11) NOT N ...
- 牛客 SQL:获取每个部门中当前员工薪水最高的相关信息
题目:获取每个部门中当前员工薪水最高的相关信息 代码: SELECT de.dept_no, de.emp_no, sa.salary FROM dept_emp AS de INNER JOIN s ...
- LeetCode(SQL)难度-中等
LeetCode(SQL)难度-中等 注:排名知识点(题目1->思路来源于牛客-小数志(公众号)) 连续排名,例如3000,2000,2000,1000排名结果为1-2-3-4,体现同薪不同名, ...
- Mysql练习题13- 员工薪水中位数
需求:请编写SQL查询来查找每个公司的薪水中位数.挑战点:你是否可以在不使用任何内置的SQL函数的情况下解决此问题. 展示效果: Id Company Salary 5 A 451 6 A 513 1 ...
- 【持续更新】Leetcode SQL题目全解析(附建表sql)
Leetcode SQL题目全解析 越前须知(雾) 题目Q & A 175 组合两个表 181 超过经理收入的员工 182 查找重复电子邮箱 183 从不订购的用户 197 上升的温度 511 ...
- 台积电全球员工薪酬中位数约46万,CEO约899万;苹果上调日本的 iPhone 售价 ;Vim 9.0 发布|极客头条...
「极客头条」-- 技术人员的新闻圈! CSDN 的读者朋友们早上好哇,「极客头条」来啦,快来看今天都有哪些值得我们技术人关注的重要新闻吧. 整理 | 梦依丹 出品 | CSDN(ID:CSDNnews ...
- 谷歌员工年薪中位数近190万元!科技公司年薪排行,哪家强?
雷科技.腾讯科技 | 报道 据报道,由于美国科技股动荡,导致越来越依靠股权奖励的美国科技巨头的员工薪酬受到影响,但他们的收入依然高于绝大多数行业. 根据各大公司提交给美国证券交易委员会(SEC)的文件 ...
最新文章
- Mycat分片规则详解
- 特斯拉遇上 CPU:程序员的心思你别猜
- 【100题】第五十九题 用C++编写不能被继承的类
- if test project can't be opened in devenv
- 崩坏3服务器维护多久,崩坏35月28日停服维护多久?4.0版本更新内容汇总[图]
- XNA 游戏 运行时编辑器
- Ubuntu下安装最新版QQ
- 2020山东省计算机专科学校排名,2021山东专科学校排名 最好的高职院校排行榜
- Xcode 6.0中彻底关闭ARC
- powerdesigner 导出mysql 库,自动生成ER图
- Linux下常用的优秀软件
- UU跑腿前端中台方案
- linux copy 复制文件夹及子文件夹
- c++自动抢购_淘宝 2020双十一最新版 全自动做任务软件 超级星秀猫 来了!上车~...
- 【论文阅读】RegNet-Designing Network Design Space
- 【Vue学习笔记_05】v-on事件监听
- Flutter安装后出现HTTP host not reachable.
- 求最长递增子序列个数——C++
- iOS 模拟各种网络环境
- 多平台如何发布文章?
热门文章
- N的阶乘末尾有几个零C语言,N的阶乘末尾有多少个零?
- 视频交友直播软件源码开发的必备功能讲解
- 【PB】TriggerEvent()/Event()/PostEvent()有什么不同
- could not execute menu item系统找不到指定的文件
- 谷歌搜索突显网站的ICO图标和网址
- Homebrew安装与配置(macOS)
- Chinajoy现场看点直播 猪厂的厂花逗比范 第五人格手办辣眼睛还想带回家
- ubuntu安装pip3一直失败的解决方法
- Eclipse创建Maven项目报错处理Could not resolve archetype
- 免费的包噪音网站分享