看了几个大佬写的题解,确实都很厉害,在这里我再提出一种新的解法(因为当初看题解的时候自己其实已经做到最后一步了,就想花点时间去按照自己的思路写出来,不想半途放弃o(╥﹏╥)o)

1 首先还是利用 sum() over()窗口函数求出各等级最差排名

select grade,number,sum(number) over(order by grade) max_rank
from class_grade

alt

2 用 最差排名-此等级人数+1 可得到此等级最好排名

select a.grade,a.number,a.max_rank-a.number+1 min_rank,max_rank
from(select grade,number,sum(number) over(order by grade) max_rank
     from class_grade) a

alt

按照我本来的思路我是准备用上面的结果跟(得到的中位数:偶数则2个,奇数则1个)进行非等值连接 between min_rank and max_rank 来选出中位数所在的等级。本来想用 case when 或者if 来做,但是我发现 case when then的后面好像接不了两个值(就比如偶数的时候需要返回2个中位数),然后我就想能不能在when的后面和then的后面放查询语句,发现也不行,最后没办法了突然想到查两次,然后根据联合查询union的去重作用(union all 不去重)写两个查询,偶数的时候对应不同的返回 代码如下:

SELECT
		case sum(number)%2
		when 0 then sum(number)/2
		ELSE floor((sum(number)+1)/2)
		END mid_grade
FROM class_grade
UNION
SELECT
		case sum(number)%2
		when 0 then sum(number)/2+1
		ELSE floor((sum(number)+1)/2)
		END
FROM class_grade

alt

最后两表进行连接得到最终结果:

select b.grade
from(
    select a.grade,a.number,a.max_rank-a.number+1 min_rank,max_rank
    from(
        select grade,number,sum(number) over(order by grade) max_rank
        from class_grade) a) b
right join(
			SELECT
			case sum(number)%2
			when 0 then sum(number)/2
			ELSE
					floor((sum(number)+1)/2)
			END mid_grade
			FROM class_grade
		UNION
			SELECT
			case sum(number)%2
			when 0 then sum(number)/2+1
			ELSE
					floor((sum(number)+1)/2)
			END
			FROM class_grade) c
on c.mid_grade between b.min_rank and b.max_rank
order by b.grade;

alt