首页 > 试题广场 >

获得积分最多的人(三)

[编程题]获得积分最多的人(三)
  • 热度指数:69508 时间限制: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
多个子查询暴力解决:
select 
zi4.user_id
,name
,gn
from
(
select 
user_id
,rank()over(order by gn desc) r
,gn
from
(
select 
zi1.user_id
,case when sgn1>=sgn2 then sgn1-sgn2 else if(sgn2>sgn1,0,sgn1) end gn
from
(
select user_id
,sum(grade_num) sgn1
from
grade_info
where type='add'
group by user_id
) zi1 left join
(
select user_id
,sum(grade_num) sgn2
from
grade_info
where type='reduce'
group by user_id
) zi2
on zi1.user_id=zi2.user_id
) zi3
) zi4
left join user
on zi4.user_id=user.id
where r=1

发表于 2025-02-07 10:21:13 回复(0)
#查找积分最高的用户的id,名字,以及他的总积分是多少(可能有多个),查询结果按照id升序排序
#id name    grade_num
select a.id,a.name,b.grade_num from user a
inner join
(
    select user_id ,sum(grade_num) grade_num,dense_rank()
    over(order by sum(grade_num) desc) rn
    from (
select user_id,case when type='reduce' then -1*grade_num  
when type='add' then grade_num
end  grade_num from grade_info
) t
group by user_id
) b on a.id=b.user_id
where b. rn=1
发表于 2024-12-06 11:23:18 回复(0)
SELECT
    id,
    name,
    result
FROM(
    SELECT
        user_id,
        SUM(CASE
            WHEN type = 'add' THEN grade_num
            ELSE -grade_num
        END) AS result,
        RANK() OVER (ORDER BY SUM(CASE WHEN type = 'add' THEN grade_num ELSE -grade_num END) DESC) t_rank
    FROM grade_info
    GROUP BY user_id
) a
JOIN user u
ON a.user_id = u.id
WHERE t_rank = 1
-- CASE作为SUM聚合函数的一部分,不必为CASE指定别名,只需为SUM聚合函数指定别名就行了
-- 想将某一列的数取赋值,直接在列名前面加个负号即可

发表于 2024-10-30 21:51:21 回复(0)
select distinct
    u.id,
    u.name,
    d.sum_num grade_num
from
    (
        select
            *,
            max(sum_num) over () max_num
        from
            (
                select
                    *,
                    sum(case when type ="add" then grade_num 
                         else -grade_num end) 
                    over (
                        partition by
                            user_id
                    ) sum_num
                from
                    grade_info
            ) t
    ) d
    left join user u on u.id = d.user_id
where
    max_num = sum_num
order by  u.id

发表于 2024-10-24 10:45:34 回复(0)
with
    a as (
        select
            *,
            if (type = 'add', grade_num, - grade_num) new_grade
        from
            grade_info
    ),
    b as (
        select
            user_id,
            sum(new_grade) as new_grade
        from
            a
        group by
            user_id
    )
select
    c.user_id,
    c.name,
    c.new_grade
from
    (
        select
            b.*,
            user.name,
            rank() over (
                order by
                    new_grade desc
            ) rk
        from
            b
            join user on b.user_id = user.id
    ) c
where
    rk = 1


发表于 2024-10-07 23:08:40 回复(0)
with usergrade as
(select e1.user_id,e1.gradenum-e2.gradenum as grade_num
from (select user_id,sum(grade_num) as gradenum,type
from grade_info
group by user_id,type) as e1
left outer join (select user_id,sum(grade_num) as gradenum,type
from grade_info
group by user_id,type)  as e2
on e1.user_id = e2.user_id
where  e1.type = 'add' and e2.type<>e1.type
union
select user_id,sum(grade_num) as grade_num
from grade_info
where user_id not in(
select user_id
from grade_info
where type = 'reduce')
group by user_id)

select e.id,name,e.grade_num
from (select e2.id,name,grade_num,rank() over (order by grade_num desc) as rnum
from usergrade as e1 ,user as e2
where e1.user_id = e2.id) as e
where e.rnum=1

发表于 2024-09-09 22:18:46 回复(0)

注意加减方法,可以先通过判断将加减运算体现出来,我用的是case-when,if方法也是可以的
体现出加减运算之后,然后就可以直接求和算排名第一的了,然后把排名第一的筛选出来就好

select t1.user_id, t2.name, t1.final_num
from (
    select user_id, sum(real_num) as final_num
    , dense_rank() over(order by sum(real_num) desc) as rn
    from (
        select *
        , case when type = 'add' then 0+grade_num 
            when type = 'reduce' then 0-grade_num
            else grade_num end as real_num
        from grade_info
    ) t
    group by user_id
) t1 left join user t2 on t1.user_id = t2.id
where t1.rn = 1
order by t1.user_id asc
发表于 2024-08-15 11:25:41 回复(0)
select id, name, grade_num
from 
(
select *,
dense_rank() over(order by grade_num desc) as grade_rank
from
    (
    select id, name, ifnull(grade_num, 0) as grade_num
    from user as t7
    left join
    (
    select t5.id as user_id,
    add_grade_num - reduce_grade_num as grade_num
    from
    (
        (
        select id, name, ifnull(add_grade_num, 0) as add_grade_num
        from user as t3
        left join
            (
            select user_id,
            sum(grade_num) as add_grade_num
            from grade_info
            where type='add'
            group by user_id
            ) as t1
        on t3.id = t1.user_id
        ) as t5
    left join
        (
        select id, name, ifnull(reduce_grade_num, 0) as reduce_grade_num
        from user as t4
        left join
            (
            select user_id,
            sum(grade_num) as reduce_grade_num
            from grade_info
            where type='reduce'
            group by user_id
            ) as t2
        on t4.id = t2.user_id
        ) as t6
    on t5.id = t6.id
    )
    ) as t8
    on t7.id = t8.user_id
    ) as t9
) as t10
where grade_rank = 1
order by id;

发表于 2024-07-30 13:02:28 回复(0)
select
t3.user_id,t4.name,t3.scnt
from (
select
user_id,scnt,dense_rank()over(order by scnt desc) dr
from (
select
user_id,sum(cnt) scnt
from (
select
user_id,case when type='add' then grade_num
       else -grade_num  end cnt
from grade_info
)t1
group by user_id
)t2
)t3
inner join user t4
on t3.user_id=t4.id
where t3.dr=1
order by t3.user_id
;
发表于 2024-07-21 16:55:23 回复(0)
select bb1.id,bb1.name,bb1.ff
from
(
select distinct(aa.id),aa.name,aa.ff,dense_rank()over(order by aa.ff desc) pp
from (
select distinct(bb.id),bb.name,bb.gg,
sum(bb.gg)over(partition by bb.id ) ff
from(
select a.id,a.name,b.grade_num,
if(b.type ='add',grade_num,-grade_num) gg
from user a
left join grade_info  b
on a.id = b.user_id
) bb
) aa
) bb1
where bb1.pp=1
order by bb1.id asc
发表于 2024-05-30 23:43:50 回复(0)
select user.id
,user.name
,rt2.last_grade
from
(
    select rt1.user_id
    ,rt1.last_grade last_grade
    ,dense_rank()over(order by last_grade desc) rk
    from
    (
        select g1.user_id user_id
        ,(g1.add_grade - ifnull(g2.reduce_grade,0)) last_grade
        from
        (
            select user_id
            ,sum(grade_num)over(partition by user_id order by grade_num desc) add_grade
            from grade_info
            where grade_info.type='add'
        ) g1 left join
        (
            select user_id
            ,sum(grade_num)over(partition by user_id order by grade_num desc) reduce_grade
            from grade_info
            where grade_info.type='reduce'
        ) g2 on g1.user_id=g2.user_id
    ) rt1
) rt2 join user on user.id=rt2.user_id
where rt2.rk=1

为什么自测用例能通过但是题目的测试用例并没有全部通过?
发表于 2024-05-19 02:32:06 回复(0)
#1.首先查询每个用户各个的累计积分
with t as(
    select user_id,sum(case when type='add' then grade_num
                            when type='reduce' then (-1)*grade_num
                        end) as sum_grade_num
    from grade_info
    group by user_id
)

#2.再根据累计表查询分数最高的用户数据
select id,name,sum_grade_num as grade_num
from user u
inner join t on u.id = t.user_id
where sum_grade_num = (
    select max(sum_grade_num)
    from t
)
order by user_id asc;

发表于 2024-05-08 10:40:51 回复(0)
select  user.id,name,p
from user inner join (
select user_id,p
from(
select  user_id,sum(defen)p ,rank() over(order by sum(defen) desc) rk
from (
select user_id,case when type='add' then grade_num else  0-grade_num end defen
from grade_info
)t
group by user_id) y
where rk=1) h  on user.id=h.user_id
编辑于 2024-03-15 09:21:58 回复(0)
select t2.user_id,user.name,t2.real_sum from
(select t1.*,dense_rank() over(order by t1.real_sum desc) as rk from
(select t.user_id,sum(t.real_num) as real_sum from
(select user_id,
case when type = "add" then grade_num else (-1)*grade_num end as real_num
from grade_info) as t
group by t.user_id) as t1) as t2
left join user on t2.user_id = user.id
where t2.rk = 1
order by t2.user_id asc;
发表于 2024-03-10 13:16:25 回复(0)
WITH total_grade_info AS (
	SELECT 
		g.user_id AS id 
		,u.name
		,SUM(IF(type="add", grade_num, -grade_num)) AS total_grade
	FROM grade_info g
	JOIN user u ON u.id = g.user_id  
	GROUP BY 1, 2
),
rank_info AS (
	SELECT
		*
		,RANK() OVER(ORDER BY total_grade DESC) AS rnk 
	FROM total_grade_info
)
SELECT
	id 
	,name
	,total_grade AS grade_num 
FROM rank_info
WHERE rnk = 1
ORDER BY 1; 

编辑于 2024-02-26 16:57:05 回复(0)
select bb.id,bb.name,aa.grade_num
from 
(select a.user_id,a.grade_num,dense_rank() over(order by a.grade_num desc) rank_id
from
(select user_id,sum(case type when 'add' then grade_num else -1*grade_num end) grade_num
from grade_info
group by user_id
order by user_id) a)aa,user bb
where aa.user_id =bb.id
and aa.rank_id ='1'

编辑于 2024-01-03 15:33:05 回复(0)
select id,name,grade_num from
(select id,name,grade_num,rank()over(order by grade_num desc) rk from
(select id,name,sum(if(type='add',grade_num,-grade_num))grade_num from grade_info a inner join user b on a.user_id=b.id group by id,name)xb1)xb2
where rk=1
order by id
发表于 2023-12-03 15:40:20 回复(0)
select id
    ,name
    ,grade_num
from (
    select id
        ,name
        ,num grade_num
        ,dense_rank()over(order by num desc) rk
    from (
        select id
            ,name
            ,sum(case when type = 'add' then grade_num else -grade_num end) num
        from grade_info
        join user
        on grade_info.user_id = user.id
        group by id
            ,name
    ) a
) aa
where aa.rk = 1

发表于 2023-11-30 14:11:40 回复(0)

select
    user_id,
    name,
    grade_num_new
from
    (
    select
        user_id,
        name,
        grade_num_new,
        rank() over(order by grade_num_new desc) as rk
    from
        (
        select
            user_id,
            name,
            sum(grade_num_new) as grade_num_new
        from
            (
            select 
                gi.user_id,
                u.name,
                case when type = 'add' then grade_num 
                when type = 'reduce' then 0-grade_num
                else 0 end as grade_num_new
            from grade_info gi 
            left join user u on gi.user_id = u.id
            ) t0
        group by user_id,name
        ) t1
    ) t2
where rk = 1

在第二题的基础上稍作改进

发表于 2023-11-27 23:15:29 回复(0)
# 请你写一个SQL查找积分最高的用户的id,名字,以及他的总积分是多少(可能有多个),查询结果按照id升序排序


with dwd_data as (
select 
  user_id,
  sum(grade_num*if(type='add',1,-1)) as grade_num,
  rank()over(order by sum(grade_num*if(type='add',1,-1)) desc) rn
from grade_info t1 
group by user_id
)

select 
t1.user_id,
t2.name,
t1.grade_num
from dwd_data t1 
inner join user t2 on t1.user_id = t2.id
where rn =1
order by 1
;

发表于 2023-10-24 11:02:10 回复(1)