mysql如何进行组内排序?利用复合索引高效得到结果!

常见的组内排序方式有,1:子查询法:根据子查询得到组内的最小或最大值,再通过id查询数据。2:利用group_concat(name order by name desc) 得到列值顺序或倒序的拼接字符串,再使用substring函数切合得到字符串第一个元素的值。
子查询法的缺点是,需要进行子查询,所以需要用到临时表。速度比较慢

而本文介绍到的使用复合索引去查询得到组内排序结果,只需要一条普通的sql就可以了,把数据查询出来就已经是排序好的结果了,所以速度非常快。

表结构:

CREATE TABLE student_score (
id int(11) NOT NULL AUTO_INCREMENT COMMENT ‘自增id’,
name varchar(128) comment ‘姓名’,
subject varchar(128) comment ‘科目’,
score int comment ‘成绩’,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
mysql如何进行组内排序?利用复合索引高效得到结果!_第1张图片

现在需要查出每个学生成绩最高的科目纪录
先来一个很多人误以为可以的语句
select *, max(score)
from student_score
group by name

结果如下,max(score)和score是没有关系的,score的值是分组后排序第一行的值,而max(score)是分组内score最大的值,两者之间完全没有关系的
mysql如何进行组内排序?利用复合索引高效得到结果!_第2张图片

回到正题,先分析表结构name和subject是1:N的关系,而一个name里面subject与score是1:1的关系。
现在需要拿出每个name下score值最大的subject,所以我建立的索引需要满足在name相同的情况下score有序就可以了。
alter table student_score add index idx_name_socre(name,score)
mysql如何进行组内排序?利用复合索引高效得到结果!_第3张图片
如果想要每个学生成绩最低的科目只需要改成,group by name asc 或者 group by name。因为group by默认去分组内的第一条。

如果想展示每个学生每科成绩由高到底排序,这种groupby查询是很高效,既不需要临时表,也不需要额外的排序。排序的结果完全按照索引的来返回。
mysql如何进行组内排序?利用复合索引高效得到结果!_第4张图片

自从深入学习mysql后发现要学好索引,用好索引,首要还是先理解好B+数的结构,原理和优点。其实很多优化sql的方式都存在于B+树中,并不需要过多去记一招一式。

你可能感兴趣的:(mysql)