中位数求法的思路
**思路**:对于一个数组中的中位数,
1. **大于该数的数值个数**与**小于该数的数值个数$\geq$(总数个数/2)**;
2. 当数组从<font color=red>0</font>开始排序时,又可以说该数的大小排名位于 **[ floor(数组最大排名-1)/2, ceil(数组最大排名-1)/2 ]之间** ;
当数组从<font color=red>1</font>开始排序时,又可以说该数的大小排名位于 **[ floor(数组最大排名+1)/2, ceil(数组最大排名+1)/2 ]之间**
- 当数组为**奇数**时,满足条件的数字只有一个
- 当数组为**偶数**时,满足条件的数字有两个
- 因此,只要将得到的一个或两个数字取**平均值**即可
---
# 571. 给定数字的频率查询中位数(难度:<font color=red>**困难**</font>)
Numbers 表保存数字的值及其频率

在此表中,数字为 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3 ,所以中位数 是 (0 + 0) / 2 = 0 。

请编写一个查询来查找所有数字的中位数并将结果命名为 median 。
**解法:**
- **利用中位数性质**
```sql
select avg(n) as median from
(
select Number as n, @c1 + 1 as 'c1', (@c1 := @c1 + Frequency) as 'c2', t2.s
from Numbers, (select @c1 := 0) t1, ( select sum(Frequency) as s from Numbers ) t2
order by n
) tmp
where c1 <= s/2 + 1 and c2 >= s/2
```
---
# 569. 员工薪水中位数(难度:<font color=red>**困难**</font>)
Employee 表包含所有员工。 Employee 表有三列:员工Id,公司名和薪水。

请编写SQL查询来查找每个公司的薪水中位数。挑战点:你是否可以在不使用任何内置的SQL函数的情 况下解决此问题。

注:这题偶数数组它的中位数取了两个
**解法:**
**(1)变量法**
```sql
select e.Id,e.Company,e.Salary
from
(
select id, company,salary, if(@pre=company,@rank:=@rank+1,@rank:=0) 'rank', @pre:=company
from ( select * from employee order by company,salary,id) e1 , (select @pre:=null,@rank:=-1) temp
) e
inner join
(
select company, count(*) 'max'
from employee
group by Company ) e1
on e.company=e1.company
where e.rank in(floor((e1.max-1)/2),ceil((e1.max-1)/2));
```
**(2)子查询**
- 运用CASE表达式,非等值自连接和HAVING子句来找中位数
- 通过 WHERE e1.Company = e2.Company 进行分组
- 最后通过GROUP BY 去重
```sql
select Id, Company, Salary
from Employee
where Id in
(
select e1.Id
from Employee e1, Employee e2
WHERE 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
```