去网上搜了一下答案,当总数为偶数时,两个数的逆序或者顺序都会差1,使用abs()函数求绝对值;
这里还需要使用Cast是因为不转换的话,可能序列号太大超出上限,太小超出下限0,从而报错
修改一下代码:
select id,a.job,score,t_rank from( select id,job,score, cast(row_number() over (partition by job order by score desc) as signed) as t_rank, cast(row_number() over (partition by job order by score)as signed) as a_rank from grade ) as a join (select job,count(id) as cnt from grade group by job) as b on a.job=b.job where abs(a.t_rank-a.a_rank)=1 or a.t_rank=a.a_rank order by id
————————
第二次的答案:
这样写的答案居然对了,先mark一下,回头再来看
中位数为正序、逆序均大于等于整个序列数的一半
select id,a.job,score,t_rank from( select id,job,score, row_number() over (partition by job order by score desc) as t_rank, row_number() over (partition by job order by score) as a_rank from grade ) as a join (select job,count(id) as cnt from grade group by job) as b on a.job=b.job where a.t_rank>=cnt/2 and a.rank>=cnt/2 order by id
————————
第一次的答案:
分为3个步骤:
- 找到每个用户每科成绩的排名;
- 找到中位数的取值范围;
- 将排名和中位数比较;
计算排名使用窗口函数dense_rank
SELECT id,job,score, DENSE_RANK() OVER (PARTITION BY job ORDER BY score DESC) AS r FROM grade
使用case找到中位数的取值范围
SELECT job, (CASE WHEN cnt%2=1 THEN (cnt+1)/2 ELSE (cnt/2) END) AS start, (CASE WHEN cnt%2=1 THEN (cnt+1)/2 ELSE (cnt/2+1) END) AS end FROM ( SELECT job,COUNT(id) AS cnt FROM grade GROUP BY job)AS d
将上面两步联合起来,增加排名和中位数比较的条件(or)
SELECT b.id,b.job,b.score,b.r FROM ( SELECT job, (CASE WHEN cnt%2=1 THEN (cnt+1)/2 ELSE (cnt/2) END) AS start, (CASE WHEN cnt%2=1 THEN (cnt+1)/2 ELSE (cnt/2+1) END) AS end FROM ( SELECT job,COUNT(id) AS cnt FROM grade GROUP BY job)AS d) AS a JOIN (SELECT id,job,score, DENSE_RANK() OVER (PARTITION BY job ORDER BY score DESC) AS r FROM grade) AS b ON a.job=b.job WHERE b.r=a.start OR b.r=a.end ORDER BY b.id