“成绩表”记录了学生的名字,课程,学期以及对应的成绩。现在需要查找每学期每门课程的前3高成绩对应的学期,课程,姓名和分数。
题目属于分组排名类型,专用窗口函数包括rank, dense_rank, row_number,函数存在区别
如果出现两人并列第一的情况,则同为第1名;且第3人名次为2;则使用dense_rank();
结果是1,1,2,3
如果出现两人并列第一,则同为第1名,但第3人名次为3,则使用ranK();
结果是1,1,3 ,4
如果出现两人并列第一,则不考虑并列名次,排名不断增加;即使用row_number()
结果是1,2,3,4
use sql练习;
select*,rank() over (partition by class,course order by score desc)as rank1,
dense_rank() over (partition by class,course order by score desc)as rank2,
row_number() over (partition by class,course order by score desc)as rank3
from course
use sql练习;
select class,course,stu_name,score,ranking from ( select class, course, stu_name, score,
row_number() over ( partition by class, course order by score desc ) as ranking
from sql练习.course ) as x
where x.ranking <= 3
## 字段名不要使用特殊符号
判断第二个学期中前三学生名次在两个学期的变化,并输出“进步一名”,“后退一名”,“退出前三”,“进步两名”等信息;
use sql练习;
select y1.course,y1.stu_name,
(case when cast(y1.ranking as signed) - CAST(y2.ranking AS SIGNED) = 0 then '位次不变'
when cast(y1.ranking as signed) - CAST(y2.ranking AS SIGNED) = -1 then '进步一名'
when cast(y1.ranking as signed) - CAST(y2.ranking AS SIGNED) = -2 then '进步两名'
when cast(y1.ranking as signed) - CAST(y2.ranking AS SIGNED) = 1 then '后退一名'
when cast(y1.ranking as signed) - CAST(y2.ranking AS SIGNED) = 2 then '后退两名'
else '退出前三'
end)as info
from
(select course,stu_name,ranking from
(select class,course, stu_name, score,
row_number() over ( partition by class, course order by score desc ) as ranking
from sql练习.course ) as x1
where x1.ranking <= 3 and x1.class = '201906') y1
left join(select course,stu_name,ranking from
(select class, course, stu_name, score,
row_number() over ( partition by class, course order by score desc ) as ranking
from sql练习.course ) as x2
where x2.ranking <= 3 and x2.class = '201912') y2
on y1.course = y2.course and y1.stu_name = y2.stu_name
#where y2.ranking <> 'NULL'
ascending = 0,代表降序;
method = 'dense’表示并列展示第1,第2名展示第2名;
输出结果是 1,1,2,3
data['ranking']=data['score'].rank(ascending=0,method='dense')
method = 'first’表示最先出现的排名为1,其他依次递增;
输出结果是 1,2,3,4
等价于row_number()
data['ranking']=data['score'].rank(ascending=0,method='first')
method = ‘min’ 表示并列出现时展示最小值
输出结果是 1,1,3,4
不等价于ranK()
data['ranking']=data['score'].rank(ascending=0,method='min')
method = ‘max’ 表示并列出现时展示最大值
输出结果是 2,2,3,4;
不等价于ranK()
data['ranking']=data['score'].rank(ascending=0,method='max')
data['ranking']=data['score'].groupby(data['class','course']).rank(ascending=0,method='dense')
TOP 子句,用于规定要返回的记录的数目。
对于拥有数千条记录的大型表来说,TOP 子句是非常有用的。注释:并非所有的数据库系统都支持 TOP 子句。
SELECT TOP 50 PERCENT * FROM Persons;
SELECT TOP 2 * FROM Persons
SELECT column_name(s)
FROM table_name
LIMIT number
## 建表
use sql练习;
create table course (
class varchar(20),
course varchar(20),
stu_name varchar(20),
score float
);
## 输入数据
insert into course values ('201906','cs','tom',91);
insert into course values ('201906','math','sarah',68);
insert into course values ('201906','cs','amy',99);
insert into course values ('201906','math','lily',93);
insert into course values ('201906','cs','john',85);
insert into course values ('201906','math','sherry',67);
insert into course values ('201906','math','tom',91);
insert into course values ('201906','math','john',91);
insert into course values ('201906','cs','sarah',91);
insert into course values ('201906','cs','edson',91);
insert into course values ('201906','cs','sherry',91);
insert into course values ('201906','cs','lily',91);
insert into course values ('201906','math','amy',91);
insert into course values ('201906','math','edson',91);
insert into course values ('201912','cs','tom',95);
insert into course values ('201912','math','sarah',99);
insert into course values ('201912','cs','amy',95);
insert into course values ('201912','math','lily',78);
insert into course values ('201912','cs','john',85);
insert into course values ('201912','math','sherry',81);
insert into course values ('201912','math','tom',88);
insert into course values ('201912','math','john',94);
insert into course values ('201912','cs','sarah',94);
insert into course values ('201912','cs','edson',90);
insert into course values ('201912','cs','sherry',93);
insert into course values ('201912','cs','lily',75);
insert into course values ('201912','math','amy',66);
insert into course values ('201912','math','edson',55);
### 比较三种方式
SELECT *, RANK() OVER (partition by class,course order by score desc) as rank1,
dense_rank() over (partition by class, course order by score desc) as rank2,
row_number() over (partition by class, course order by score desc) as rank3
FROM sql练习.course;