【Mysql】综合成绩的中位数是什么档位

最差是第几名(二)

http://www.nowcoder.com/questionTerminal/165d88474d434597bcd2af8bf72b24f1

题目描述:老师想知道学生们综合成绩的中位数是什么档位,请你写SQL帮忙查询一下,如果只有1个中位数,输出1个,如果有2个中位数,按grade升序输出。
个人思路:
步骤一、为各个grade添加排名取值范围(t_rank,section)。
步骤二、找出总共参与考试的学生人数(total)。
步骤三、找出中位数floor((t.total+1)/2)、floor((t.total+2)/2)在哪个名次的取值范围内。

 with t_rank as  #-- 添加排名作为取值区间的最大值
(
    select grade, 
           sum(number) over(order by grade)as sec_1
    from class_grade
),
section as #--完成取值区间 ,如 A ,0,2
(
    select grade,
           ifnull(lag(sec_1) over(),0) as sec_0,
           sec_1
    from t_rank
),
total as #--找出总名次数
(
    select sum(number)as total
    from class_grade
)
#--查询出出中位数在哪个名次的取值区间,获得grade
select s.grade 
from section s ,total t
where (floor((t.total+1)/2) > sec_0 and floor((t.total+1)/2) <= sec_1)
  or (floor((t.total+2)/2) > sec_0 and floor((t.total+2)/2) <= sec_1)
order by grade

IFNULL(v1,v2) 如果 v1 的值不为 NULL,则返回 v1,否则返回 v2。
窗口函数lag(sec_1) over() 获取上一行sec_1的值。
表section的结果:
grade sec_0 sec_1
A 0 2
B 2 4
C 4 6
D 6 7
注意的是,实际上每个名次的取值范围应该是左开右闭的区间即A(0,2},B(2,4}...。所以后面用中位数进行筛选时是>sec_0 and <=sec_1。

借鉴大佬的思路:

with t_rank as
(
    select grade,
       (select sum(number) from class_grade) as total,
       sum(number) over(order by grade) a,
       sum(number) over(order by grade desc) b
    from class_grade
    order by grade
)
select grade 
from t_rank
where a>=total/2 and b>=total/2
order by grade

t_rank找出名次,总数,正序排名和倒序排名。
然后找出正序排序大于一半的同时倒序也大于一半的(实际上这不就是中位数吗╮(╯▽╰)╭)
大佬神奇的思路,赞!! (๑•̀ㅂ•́)و✧

牛客题霸-SQL篇【Mysql】 文章被收录于专栏

少壮不努力,老大勤刷题

全部评论
没有考虑奇数偶数问题,只是在该题上的结果正确
点赞 回复 分享
发布于 2021-12-20 19:35
有个问题想请教一下: 表section的结果,为什么不是: grade sec_0 sec_1 A 0 2 B 2 6 C 6 10 D 10 12 感觉这样才能从后面中位数条件判断出来?
点赞 回复 分享
发布于 2022-11-04 10:36 北京

相关推荐

评论
17
4
分享
牛客网
牛客企业服务