LeetCode --- 数据库(会员)
简书专栏:https://www.jianshu.com/nb/42460386
一、题目描述
来源:力扣(LeetCode)
Employee 表包含所有员工。Employee 表有三列:员工Id,公司名和薪水。
+-----+------------+--------+
|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 |
+-----+------------+--------+
请编写SQL查询来查找每个公司的薪水中位数。挑战点:你是否可以在不使用任何内置的SQL函数的情况下解决此问题。
+-----+------------+--------+
|Id | Company | Salary |
+-----+------------+--------+
|5 | A | 451 |
|6 | A | 513 |
|12 | B | 234 |
|9 | B | 1154 |
|14 | C | 2645 |
+-----+------------+--------+
二、解题思路以及实现
解决中位数问题思路一定要清晰,首先是要对数据进行排序,增加一个自增列让薪资从低到高排序,然后取中间位置即可。基本可以应对大多数中位数问题。
注意几点:
- @com变量用来判断是否与前一个变量相同,要放在IF判断之后
- 关联统计每组总人数的表
- 使用t.rn in (FLOOR(m.cnt/2 + 1),CEIL(m.cnt/2))来判断是否是中位数,则不需要去判断总数的奇偶数了
SELECT
t.id,
t.company,
t.salary
FROM
(
SELECT
a.id,
a.company,
a.Salary,
IF ( @com = a.company, @rn := @rn + 1, @rn := 1 ) AS rn,
@com := a.company -- 必须放在后面
FROM
Employee a,
( SELECT @rn := 1, @com := NULL ) b
ORDER BY
company,
Salary
) t
left join (SELECT company,count(*) as cnt from employee group by company) m
on t.company = m.company
where
t.rn in (FLOOR(m.cnt/2 + 1),CEIL(m.cnt/2))
若本题只有一个分组
则可以直接使用@rn来作为总人数,因为@rn从1开始,加到最后即为总人数
SELECT
t.id,
t.company,
t.salary
FROM
(
SELECT
a.id,
a.company,
a.Salary,
IF ( @com = a.company, @rn := @rn + 1, @rn := 1 ) AS rn,
@com := a.company -- 必须放在后面
FROM
Employee a,
( SELECT @rn := 1, @com := NULL ) b
ORDER BY
company,
Salary
) t
where
t.rn in (FLOOR(@rn/2 + 1),CEIL(@rn/2))