【自用】SQL题解 | 中位数计算方法总结
考试分数(五)
https://www.nowcoder.com/practice/b626ff9e2ad04789954c2132c74c0513
求中位数有三种方法,
第一种是中位数序号 距离 (数据量+1)/2 小于1,用公式表达abs(rn - (num +1)/2) < 1,注意不是<=1而是<1;
# 写法一:中位数序号 与 (个数+1)/2 的距离 小于1 ,公式为abs(rn - (num+1)/2) < 1
with t as (
select
*
,row_number() over(partition by job order by score desc) as t_rank
,count(*) over(partition by job) as cnt
from
grade
)
select
id
,job
,score
,t_rank
from
t
where
abs(t_rank - (cnt+1)/2) <1
order by id
第二种是中位数正序序号和逆序序号都大于等于数据量的一半,公式表示 rn1 >= num/2 and rn2 >= num/2 ,注意这里用的是and不是or;
# 写法二:中位数正序序号和逆序序号都大于等于num/2
with t as (
select
*
,row_number() over(partition by job order by score desc) as t_rank
,row_number() over(partition by job order by score) as t_rank2
,count(*) over(partition by job) as cnt
from grade
)
select
id,
job,
score,
t_rank
from t
where
t_rank >= cnt/2 and t_rank2 >= cnt/2
order by id
第三种是找出中位数所在的序号,如果数据量为奇数,中位数序号就为ceil(num/2);如果数据量为偶数,中位数序号为floor(num/2)和floor(num/2)+1。
# 写法三:找出中位数所在的序号,按序号搜索成绩
with t as (
select
a.*
,row_number() over(partition by a.job order by score desc) as t_rank
,case when mod(cnt,2) = 1 then ceil(cnt/2) else floor(cnt/2) end as mid1
,case when mod(cnt,2) = 1 then ceil(cnt/2) else floor(cnt/2) +1 end as mid2
from grade a
LEFT JOIN
(
select
job
,count(*) as cnt
from
grade
group by job
) b
on a.job = b.job
)
select
id
,job
,score
,t_rank
from t
where t_rank = mid1 or t_rank = mid2
order by id
