没有开窗函数over()时,纯sql查询最大值行,主要思路归纳为以下几种:
·
思路1、使用group by分组,因为分组后只会返回每组的第一行记录,所以分组前先排序,把需要的行记录排到分组的第一行,最后分组可得每组第一行数据。
·
思路2、一个表自己跟自己left join,在每个分组内,假设按age排序,则通过a.age<b.age连接后,每个a.age都会关联一组比自己大的b.age,最后统计a.age的关联数count(a.age),0表示没有b.age比自己大(a.age为最大值),1表示有一个比自己大(a.age为第二大值),最后在where中筛选count(a.age)<N则得到每组前N条。
·
思路3、直接在子查询中找出最大值,通过最大值关联查询

查询最大(小)值所在行

举例:

构造如下成绩表数据,现在需要找到各个学生最低分的科目:

MySQL根据某个字段的最大值查询 mysql查找最大的数_MySQL根据某个字段的最大值查询


1、首先找学生的最高分和最低分:

MySQL根据某个字段的最大值查询 mysql查找最大的数_性能瓶颈_02


2、进一步,如何查出各个学生最高分是哪个课程呢,很多人第一想法是找出最大值,然后用最大值匹配找到最大值的行,如下:

MySQL根据某个字段的最大值查询 mysql查找最大的数_自连接_03


因为这方式是先找出分组的最大值,然后自连接,找出连接的分组中值等于最大值的行(如果存在多个相同的最大值也会全部找出)。3、上一种方式的效率不确定,还有一种方式可以找出分组的最大最小值一行(如存在多个最大值则只返回一个):

(1)先分组并排序,这样就能看到每组的最大值了:

MySQL根据某个字段的最大值查询 mysql查找最大的数_自连接_04


上面已经可以看到每个学生最高分对应的课程了。

如何只看最高分的行记录呢?刚才只是做了排序,只需要把排序的结果按照分组条件group by一下,因为group by只会返回分组的第一行记录,所以就出来了:

MySQL根据某个字段的最大值查询 mysql查找最大的数_自连接_05


这样的性能瓶颈可能在于,需要对条件中的所有记录进行排序(如果每组记录比较小则适合使用),而上一种方式先查出最大值然后再匹配行(如果每组记录数很多适合用?但是这种方式一样需要用最大值去扫描一遍记录集)4、还看到有一种方式,就是自连接,关联的条件是,以上面举例,名字=名字,然后左边分数<右边分数:

MySQL根据某个字段的最大值查询 mysql查找最大的数_性能瓶颈_06


众所周知,如上图,名字张三左表99,右表肯定找不到分数更大的了,同理,凡是右表没有更大分数的(也就是右表id is null),左表记录就是最大值得行记录,可能出现多行最大值,这种不适合每组记录很多得情况,因为组内连接数会很大。

其他方式待发现。

综上,
1、从很多记录中找很少最大行记录,则用max函数先查询,然后在关联
2、


查询最大(小)值所在的前N行

通过分组自连,分组内统计比自己大的记录数,0个说明自己是最大值,1个说明自己是第二大,以此类推,如下图,每组筛选<2,也就是每组保留最大2个值得行记录:

MySQL根据某个字段的最大值查询 mysql查找最大的数_性能瓶颈_07