首页 > 试题广场 >

最差是第几名(一)

[编程题]最差是第几名(一)
  • 热度指数:39729 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
TM小哥和FH小妹在牛客大学若干年后成立了牛客SQL班,班的每个人的综合成绩用A,B,C,D,E表示,90分以上都是A,80~90分都是B,70~80分为C,60~70为D,E为60分以下
假设每个名次最多1个人,比如有2个A,那么必定有1个A是第1名,有1个A是第2名(综合成绩同分也会按照某一门的成绩分先后)。
每次SQL考试完之后,老师会将班级成绩表展示给同学看。
现在有班级成绩表(class_grade)如下:
grade number
A 2
D 1
C 2
B 2
第1行表示成绩为A的学生有2个
.......
最后1行表示成绩为B的学生有2个

请你写出一个SQL查询,如果一个学生知道了自己综合成绩以后,最差是排第几名? 结果按照grade升序排序,以上例子查询如下:
grade
t_rank
A 2
B 4
C 6
D 7
解析:
第1行表示,学生成绩为A的知道自己最差为第2名
第2行表示,学生成绩为B的知道自己最差为第4名
第3行表示,学生成绩为C的知道自己最差为第6名
第4行表示,学生成绩为D的知道自己最差为第7名


示例1

输入

drop table if exists class_grade;
CREATE TABLE class_grade (
grade varchar(32) NOT NULL,
number int(4) NOT NULL
);

INSERT INTO class_grade VALUES
('A',2),
('D',1),
('C',2),
('B',2);

输出

A|2
B|4
C|6
D|7
这一题虽然虽然解法简单但是还是有必要说一下:
select grade, sum(number) over(order by grade) as t_rank
from class_grade;
首先:窗口函数如果没有分区的话默认是全局排序,因此最后就不需要再次排序了;
其次:窗口函数OVER()中完整的句式有三部分:分区、排序、数据行子句;这三部分都是可选的,我们最常见的就是partition by 和 order by两部分,第三部分通常都省略了,而这省略部分的默认句式为rows between unbounded preceding and current row (表示挑选的数据行为从当前窗口的第一行到当前行),刚好符合本题需要对当前数据以及之前的所有数据进行累加。所以完整的写法应该是:
select grade, 
sum(number) over(order by grade rows between unbounded preceding and current row)as t_rank
from class_grade;



发表于 2021-03-22 12:44:52 回复(10)
本题出题的题意其实主要是考察sum() over (order by ) 开窗函数,sum(a) over (order by b) 的含义是:
例如
a  b
1 2
3 4
5 6
按照b列排序,将a依次相加,得到结果,如下:
a  b  sum(a) over (order by b):
1 2    1
3 4    1+3
5 6    1+3+5

此题就是将b换成了grade,即使b列乱序也没关系,因为有order by b:
number  grade  sum(number) over(order by grade):
2    A    2
2    B    2+2
2    C    2+2+2
1    D    2+2+2+1

所以我们代码可以如下写:
select grade, sum(number) over(order by grade) t_rank 
from class_grade 
order by grade;

编辑于 2021-03-10 14:35:36 回复(0)
借前面的答案稍微整理一下,此题可分为使用窗口函数和自连接两种解法,其中窗口函数详解请看本题高赞回答。
## 使用窗口函数
select grade, sum(number) over (order by grade rows between unbounded preceding and current row) as t_rank
from class_grade


## 不使用窗口函数
select T.grade, sum(T2.number) t_rank
from class_grade T
inner join class_grade T2 on T2.grade <= T.grade
group by T.grade
order by T.grade


发表于 2021-04-11 11:57:46 回复(2)
熬夜太多脑子瓦特了,题目读了好几遍才看懂...T~T
select grade, sum(number) over(order by grade) t_rank
from class_grade;
不过难得第一次提交就成功了,值得庆祝一下![]~( ̄▽ ̄)~*
发表于 2021-03-11 01:37:38 回复(4)
终于看明白了,一共七个人,得a的一共有两个人,a最差是第二名;b一共有两个人,则b最差是第四名,所以t_rank就是求累计和
发表于 2021-06-11 13:33:58 回复(0)
1、'A'<'B',可以直接比对
select g1.grade,sum(g2.number) as number
from class_grade g1
INNER JOIN class_grade g2 on g1.grade>=g2.grade
group by g1.grade
order by g1.grade asc;

编辑于 2021-03-29 23:13:00 回复(2)
好喜欢用两个表的做法
select c.grade,sum(c1.number) t_rank 
from class_grade c,class_grade c1 
where c.grade>=c1.grade 
group by c.grade 
order by c.grade asc
发表于 2021-11-28 13:59:42 回复(0)
#解题思路: 不可避免,还是用开窗函数计算
该题引申含义就是对number做累加
select grade, sum(number) over(order by grade) as t_rank
from class_grade
order by grade


发表于 2022-04-20 14:59:41 回复(0)
select a.grade,
(select sum(s2.number) from class_grade s2 where grade<=a.grade)
as t_rank 
from class_grade a 
order by a.grade
发表于 2022-04-12 17:28:25 回复(2)
SELECT grade,SUM(number)OVER(ORDER BY grade) t_rank
FROM class_grade
ORDER BY grade
编辑于 2021-03-10 16:29:47 回复(0)
卧槽,本来想夸下自己聪明解出来了,看了评论区才发现我TM想太多了。用上了递归解法,如下
WITH RECURSIVE t1 as (
    SELECT 1 as num
    UNION ALL
    SELECT num + 1 FROM t1 WHERE num <= (SELECT sum(number) FROM class_grade)
),
               t2 as (
    SELECT c.grade, t1.num
    FROM class_grade as c LEFT JOIN t1
    ON c.number >= t1.num
)
SELECT grade, max(rk) as t_rank
FROM (
    SELECT grade, row_number() over(order by grade) as rk
    FROM t2
) as t3
GROUP BY grade
ORDER BY grade


发表于 2021-12-16 13:00:28 回复(0)
SELECT    
    grade,
    CONVERT(@sum := @sum + number, SIGNED) AS t_rank
FROM
    (SELECT * FROM class_grade ORDER BY grade) AS a,
    (SELECT @sum := 0) AS b

发表于 2021-10-20 09:44:37 回复(2)
select grade,sum(number) over (order by grade) as t_tank
from class_grade
发表于 2025-02-06 11:52:02 回复(0)
select grade ,sum(number) over(order by grade) t_rank from class_grade;

发表于 2025-01-09 18:02:56 回复(0)
SELECT
    grade,
    SUM(number) OVER (ORDER BY grade)
FROM class_grade
发表于 2024-10-29 17:07:43 回复(0)
select grade,
       sum(number) over(order by grade ) as number
from class_grade
order by grade 
根据等级,做一个累计和
发表于 2024-10-22 20:06:25 回复(0)
select grade, sum(number) over (order by grade) as t_rank
from class_grade
order by grade

发表于 2024-09-24 13:38:17 回复(0)

select grade
      ,sum(number)over(order by grade)as t_rank
from class_grade

发表于 2024-09-23 17:22:58 回复(0)
SELECT
    grade,
    SUM(number)OVER(ORDER BY grade) t_rank
FROM
    class_grade

发表于 2024-09-08 17:35:43 回复(0)
select grade,
sum(number) over (order by grade) as t_ranK
FROM class_grade
简单的窗口函数累计求和
发表于 2024-09-04 12:42:48 回复(0)