首页 > 试题广场 >

获得积分最多的人(三)

[编程题]获得积分最多的人(三)
  • 热度指数:72921 时间限制: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 id,name,grade_num 
from
    (select id,
            name,
            grade_num,
            rank()over(order by grade_num desc) as r
    from    
       (select user_id,
               sum(if(type='add',grade_num,-1*grade_num)) as grade_num
        from grade_info
        group by user_id)f#求得每个用户的总分
    left join user u
    on f.user_id = u.id)f1#对用户总分进行排序
where r=1#选择总分最高的用户

发表于 2025-06-30 15:36:04 回复(0)
with a as (select u.id , u.name , 
sum(case when g.type = 'add' then grade_num else -grade_num end)over(partition by u.id) grade_num
from grade_info g join user u on g.user_id = u.id
order by id),
b as (select * ,rank()over( order by grade_num desc) rk from a)
select distinct id,name,grade_num from b where rk = 1
order by id
1.窗口函数sum里用case when给出每个id的积分和
2.窗口函数rank来给出根据上表得出的grade_num的排名
3.主函数随便操作一下就得出结果
发表于 2025-05-11 16:34:18 回复(0)
with t1 as(
select a.id,a.name, b.type,
    case when type='add' then grade_num else 0 end as `add`,
    case when type='reduce' then grade_num else 0 end as reduce
    from user a
    left join grade_info b
    on a.id=b.user_id
    )
   ,t2 as
   (
    select distinct id,name,
    sum(`add`)over (partition by id) as add_grade,
    sum(reduce) over(partition by id) *(-1) as reduce_grade
    from t1
)
,t3 as(
select id,name,add_grade+reduce_grade as grade_num
from t2
)
,t4 as(
    select id,name,grade_num,
    dense_rank()over(order by grade_num desc) as rk
    from t3
)
select id,name,grade_num
from t4
where rk=1
order by id
发表于 2025-04-10 12:56:49 回复(0)
with
    k as (
        SELECT
            user_id,
            CASE
                WHEN type = "add" Then grade_num
                ELSE - grade_num
            END num1
        from
            grade_info
    ),
    k1 as (
        select
            id,
            name,
            sum(num1) grade_num ,
            dense_rank() over (
                order by
                sum(num1) desc
            ) rk
        from
            user a
            left join k on a.id = k.user_id
        group by id,name
    )
select
    id,name,grade_num
from k1
where rk=1

发表于 2025-04-08 13:15:54 回复(0)
with t1 as(
select user_id,sum(if(type='reduce',-grade_num,grade_num)) as grade_num,
dense_rank() over(order by sum(if(type='reduce',-grade_num,grade_num)) desc) as rk
from grade_info
group by user_id
)

select b.id,b.name,a.grade_num
from t1 as a
inner join user as b on a.user_id = b.id
where rk=1
order by b.id

发表于 2025-03-18 13:28:45 回复(0)
with t01 as(
    select sum(case when type = 'add' then grade_num else grade_num*-1 end) as grade_num,
           user_id as id
        from grade_info
        group by user_id
)
select a.id as id,
       b.name as name,
       a.grade_num as grade_num
    from t01 a
    left join user b
    on a.id = b.id
    where a.grade_num = (select max(grade_num) from t01)
    order by id;
发表于 2025-03-13 00:29:59 回复(0)
with t1 as (
    select
        user_id,
        sum(if(type = 'add',grade_num,-grade_num)) grade_num
    from grade_info
    group by user_id
),
t2 as (
    select
        user_id,
        grade_num,
        dense_rank() over(order by grade_num desc) dr 
    from t1
)
select
    user_id,
    name,
    grade_num
from t2 
join user u 
on t2.user_id = u.id
where dr = 1
order by user_id;

发表于 2025-03-11 14:17:45 回复(0)
多个子查询暴力解决:
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)