解题思路

一、难点

1.要让add一栏的分数减去reduce一栏的分数,最后汇总才是用户最后的分数。这个应该怎么表达出来?

2.最后的汇总分数算出来之后应该怎么进行排名

二、难点解答:

解决问题1:add一栏的分数无法直接去减,但是换一个想法,让它去加一个负数呢?这样的话,我们就可以表达出来了:

sum(if(type = 'add', grade_num, -grade_num))

上面一步解决了最后分数汇总的问题,下面我们先把这一步的代码用进去,写出来看看:

select *,
    sum(if(type = 'add', grade_num, -grade_num)) as s
from grade_info
group by user_id
order by s desc

运行结果如下,是我们想要的答案:

alt

用户2,4,5正好是我们需要的。而且只要我们取出分数排名为1的用户,就可以了。

解决问题2: 如果我们能够在第一步的基础上,直接把排名问题解决了。那这道题就基本上解决了,因为最后一步只剩下和user表进行连接。能不能用dense_rank()over(order by * )来解决?于是我就尝试了一下,把第一步计算出来最后汇总分数的代码给套进去,就变成了这个样子:

dense_rank()over(order by sum(if(type = 'add', grade_num, -grade_num)) desc) as R

再把它加入第一步的代码当中:

select *,
    sum(if(type = 'add', grade_num, -grade_num)) as s,
    DENSE_RANK() over(order by sum(if(type = 'add', grade_num, -grade_num)) desc) as R
from grade_info
group by user_id
order by s desc

来运行看看:

alt

居然可以!!!接下来就好办了,最后一步,把两张表连接在一起:

select a.user_id, u.name, a.s
from
(select *,
    sum(if(type = 'add', grade_num, -grade_num)) as s,
    DENSE_RANK() over(order by sum(if(type = 'add', grade_num, -grade_num)) desc) as R
from grade_info
group by user_id
order by s) as a
join user as u
on a.user_id = u.id
where R=1
order by a.user_id