SQL10天训练---(一)分组排名

分组排名

“成绩表”记录了学生的名字,课程,学期以及对应的成绩。现在需要查找每学期每门课程的前3高成绩对应的学期,课程,姓名和分数。
SQL10天训练---(一)分组排名_第1张图片

题目属于分组排名类型,专用窗口函数包括rank, dense_rank, row_number,函数存在区别

1. 考虑3种情况

如果出现两人并列第一的情况,则同为第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

SQL10天训练---(一)分组排名_第2张图片

2. 选择前3且不并列

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

## 字段名不要使用特殊符号

SQL10天训练---(一)分组排名_第3张图片

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'

SQL10天训练---(一)分组排名_第4张图片

4. python中相似操作

  • dense_rank()

ascending = 0,代表降序;
method = 'dense’表示并列展示第1,第2名展示第2名;
输出结果是 1,1,2,3

data['ranking']=data['score'].rank(ascending=0,method='dense')
  • row_number()

method = 'first’表示最先出现的排名为1,其他依次递增;
输出结果是 1,2,3,4
等价于row_number()

data['ranking']=data['score'].rank(ascending=0,method='first')
  • min

method = ‘min’ 表示并列出现时展示最小值
输出结果是 1,1,3,4
不等价于ranK()

data['ranking']=data['score'].rank(ascending=0,method='min')
  • max

method = ‘max’ 表示并列出现时展示最大值
输出结果是 2,2,3,4;
不等价于ranK()

data['ranking']=data['score'].rank(ascending=0,method='max')
  • python 分组组内排序;
data['ranking']=data['score'].groupby(data['class','course']).rank(ascending=0,method='dense')

5. 辨析top语句

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;

你可能感兴趣的:(sql,分组排名,sql,数据库)