首页 > 试题广场 >

获得积分最多的人(三)

[编程题]获得积分最多的人(三)
  • 热度指数:70536 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
牛客每天有很多用户刷题,发帖,点赞,点踩等等,这些都会记录相应的积分。
有一个用户表(user),简况如下:
id name
1 tm
2 wwy
3 zk
4 qq
5 lm

还有一个积分表(grade_info),简况如下:
user_id grade_num type
1 3 add
2 3 add
1 1 reduce
3 3 add
4 3 add
5 3 add
3 1 reduce
第1行表示,user_id为1的用户积分增加了3分。
第2行表示,user_id为2的用户积分增加了3分。
第3行表示,user_id为1的用户积分减少了1分。
.......
最后1行表示,user_id为3的用户积分减少了1分。

请你写一个SQL查找积分最高的用户的id,名字,以及他的总积分是多少(可能有多个),查询结果按照id升序排序,以上例子查询结果如下:
id name grade_num
2 wwy 3
4 qq 3
5 lm 3
解释:
user_id为1和3的先加了3分,但是后面又减了1分,他们2个是2分,
其他3个都是3分,所以输出其他三个的数据。

示例1

输入

drop table if exists user;
drop table if exists grade_info;

CREATE TABLE user (
id  int(4) NOT NULL,
name varchar(32) NOT NULL
);

CREATE TABLE grade_info (
user_id  int(4) NOT NULL,
grade_num int(4) NOT NULL,
type varchar(32) NOT NULL
);

INSERT INTO user VALUES
(1,'tm'),
(2,'wwy'),
(3,'zk'),
(4,'qq'),
(5,'lm');

INSERT INTO grade_info VALUES
(1,3,'add'),
(2,3,'add'),
(1,1,'reduce'),
(3,3,'add'),
(4,3,'add'),
(5,3,'add'),
(3,1,'reduce');

输出

2|wwy|3
4|qq|3
5|lm|3
头像 黑猫5454
发表于 2021-03-31 11:03:00
时间复杂度最小的写法(空间占用多),首先我们这里借用2层子查询,第一层查出所有人的累计积分sum(if),第二层我们借助窗口函数直接给他排序标上排名值 最后我们直接选取排名为1的数据就出结果啦,简单清晰,(小贴士 rank dense_rank row_number大家自己了解下排序的值 展开全文
头像 一洛玉壶冰
发表于 2021-04-01 16:56:37
sum嵌套if/iif/case...when计算总积分,需要多次嵌套复用子查询时,可以创建临时表,提高执行效率和代码可读性,代码如下: with gs AS (select u.id, u.name, sum(case when gi.type='add' then gi.gra 展开全文
头像 SunburstRun
发表于 2021-03-30 15:39:46
通过(二) ,https://blog.nowcoder.net/n/16f63360bbeb4ecabbfd45c492c8567e 我们知道,全是加的时候是怎么做的,但是出现了减,有点难办了,但是可以看看这个题目的解法: https://blog.nowcoder.net 展开全文
头像 高质量搬砖人
发表于 2021-04-03 13:04:09
在前面几道题的基础上用数据转置case when解决问题 select u.id, u.name , a.grade from (select user_id , g.grade , rank()over(order by g.grade desc) r_number from (select us 展开全文
头像 Ding_123
发表于 2021-12-10 16:35:23
知识点 和上一题代码思路一模一样就是求和的时候使用case when函数,当type是reduce的时候是grade_num*-1否则就是grade_num,其他都一样。 代码 with a as( select distinct u.id,u.name, 展开全文
头像 牛客175957298号
发表于 2021-06-24 23:40:12
总体思路:1.根据user_id,分组求其总grade_num2.对grade_num排名,并取排名为1的记录信息3.join on 'user'表,得到完整信息 代码: select u.id, u.name, t1.grade from (select t.user_ 展开全文
头像 广东菜心
发表于 2021-10-18 15:42:19
利用rank() over()求解 在最内层的a表中,用case when处理好加减法的情况,把用户的总积分算出来。出现'type=reduce'的情况就等于0-grade_num,把积分转换成负数。 在第中间层的b表中利用rank() over()对a表已经算好的积分进行降序排序。 将user表 展开全文
头像 取名困难户
发表于 2021-06-14 00:04:20
下面代码是获得积分最多的人(一)(二)(三)的通解,第一题只是将第一行后的a.id去掉就可以了!~思路如下: - 1.求每个用户的总积分 - 2.题意中相同积分需要输出,按总积分采用dense_rank() over()排序,取排名为1即可 SELECT a.id, a.n 展开全文
头像 Vigoroushui
发表于 2021-05-28 10:40:30
整体思路:与「获得积分最多的人(二)」如出一辙,唯一需要注意的add的时候需要+,reduce的时候需要-,那么在构造新表new_grade的时候需要创建临时表t,逻辑如下: 包含两个列 user_id 和 new_num,针对于new_num: 如果type='add',那么直接取grade_n 展开全文
头像 七七七w
发表于 2021-09-20 15:10:51
一、相较于上一题,只有最里面这一层子查询算总分出现了变动,我考虑的是,用增加的分数和-减去的分数和。相比其他人的答案,他们的思路是对每一条分数做出判断,是加或者是减,之后再sum,本题的运行包含了两个sum时间会长一点。 select user_id, sum(if( type='add',gr 展开全文