欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MySQL分类排名和分组TOP N实例详解

程序员文章站 2022-03-01 13:16:26
目录表结构题目一:获取每个科目下前五成绩排名(允许并列)分析:题目二:获取每个科目下最后两名学生的成绩平均值分析:题目三:获取每个科目下前五成绩排名(不允许并列)分析:总结表结构学生表如下:creat...

表结构

学生表如下:

create table `t_student` (
  `id` int not null auto_increment,
  `t_id` int default null comment '学科id',
  `score` int default null comment '分数',
  primary key (`id`)
);

数据如下: 

MySQL分类排名和分组TOP N实例详解

题目一:获取每个科目下前五成绩排名(允许并列)

允许并列情况可能存在如4、5名成绩并列情况,会导致取前4名得出5条数据,取前5名也是5条数据。

select
	s1.* 
from
	student s1
	left join student s2 on s1.t_id = s2.t_id 
	and s1.score < s2.score 
group by
	s1.id
having
	count( s2.id ) < 5 
order by
	s1.t_id,
	s1.score desc

MySQL分类排名和分组TOP N实例详解

  ps:取前4名时

MySQL分类排名和分组TOP N实例详解

 分析:

1.自身左外连接,得到所有的左边值小于右边值的集合。以t_id=1时举例,24有5个成绩大于他的(74、64、54、44、34),是第6名,34只有4个成绩大于他的,是第5名......74没有大于他的,是第一名。

select
	* 
from
	student s1
	left join student s2 on s1.t_id = s2.t_id 
	and s1.score < s2.score 

MySQL分类排名和分组TOP N实例详解

  2. 把总结的规律转换成sql表示出来,就是group by 每个student 的 id(s1.id),having统计这个id下面有多少个比他大的值(s2.id)

select
	s1.* 
from
	student s1
	left join student s2 on s1.t_id = s2.t_id 
	and s1.score < s2.score 
group by
	s1.id
having
	count( s2.id ) < 5 

MySQL分类排名和分组TOP N实例详解

 3. 最后根据 t_id 分类,score 倒序排序即可。

题目二:获取每个科目下最后两名学生的成绩平均值

取最后两名成绩

select
	s1.* 
from
	student s1
	left join student s2 on s1.t_id = s2.t_id 
	and s1.score > s2.score 
group by
	s1.id 
having
	count( s1.id )< 2 
order by
	s1.t_id,
	s1.score

并列存在情况下可能导致筛选出的同一t_id 下结果条数大于2条,但题目要求是取最后两名的平均值,多条平均后还是本身,故不必再对其处理,可以满足题目要求。 

MySQL分类排名和分组TOP N实例详解

 分组求平均值:

select
	t_id,avg(score)
from
	(
	select
		s1.*
	from
		student s1
		left join student s2 on s1.t_id = s2.t_id 
		and s1.score > s2.score
	group by
		s1.id 
	having
		count( s1.id )< 2 
	order by
		s1.t_id,
		s1.score 
	) tt 
group by
	t_id

结果: 

MySQL分类排名和分组TOP N实例详解

分析:

1. 查询出所有t1.score>t2.score 的记录

select
		s1.*,s2.*
	from
		student s1
		left join student s2 on s1.t_id = s2.t_id 
		and s1.score > s2.score

MySQL分类排名和分组TOP N实例详解

2. group by s.id 去重,having 计数取2条

3. group by t_id 分别取各自学科的然后avg取均值

题目三:获取每个科目下前五成绩排名(不允许并列)

select
	* 
from
	(
	select
		s1.*,
		@rownum := @rownum + 1 as num_tmp,
		@incrnum :=
	case
			
			when @rowtotal = s1.score then
			@incrnum 
			when @rowtotal := s1.score then
			@rownum 
		end as rownum 
	from
		student s1
		left join student s2 on s1.t_id = s2.t_id 
		and s1.score > s2.score,
		( select @rownum := 0, @rowtotal := null, @incrnum := 0 ) as it 
	group by
		s1.id 
	order by
		s1.t_id,
		s1.score desc 
	) tt 
group by
	t_id,
	score,
	rownum 
having
	count( rownum )< 5

MySQL分类排名和分组TOP N实例详解

 分析:

1.引入辅助参数

select
	s1.*,
	@rownum := @rownum + 1 as num_tmp,
	@incrnum :=
case
		
		when @rowtotal = s1.score then
		@incrnum 
		when @rowtotal := s1.score then
		@rownum 
	end as rownum 
from
	student s1
	left join student s2 on s1.t_id = s2.t_id 
	and s1.score > s2.score,
	( select @rownum := 0, @rowtotal := null, @incrnum := 0 ) as it

MySQL分类排名和分组TOP N实例详解

2.去除重复s1.id,分组排序

select
		s1.*,
		@rownum := @rownum + 1 as num_tmp,
		@incrnum :=
	case
			
			when @rowtotal = s1.score then
			@incrnum 
			when @rowtotal := s1.score then
			@rownum 
		end as rownum 
	from
		student s1
		left join student s2 on s1.t_id = s2.t_id 
		and s1.score > s2.score,
		( select @rownum := 0, @rowtotal := null, @incrnum := 0 ) as it 
	group by
		s1.id 
	order by
		s1.t_id,
		s1.score desc 

MySQL分类排名和分组TOP N实例详解

 3.group by    t_id, score, rownum   然后 having 取前5条不重复的

总结

到此这篇关于mysql分类排名和分组top n实例详解的文章就介绍到这了,更多相关mysql分类排名 top n内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!