碰到了两次这种面试题目,居然理所当然的以为自己很聪明,轻松解决,不料自己还是太年轻。

题目的需求大致是这样的:希望你通过分组后取出组里面的最大的数据

一开始思路如此: 不是很简单吗,直接排序后分组,秒杀。

后来又碰到类似的面试题,直接一把梭,秒杀

后来想了想,貌似ORDERR BY 是在GROUP BY 之后的,SQL 的执行顺序会不会有问题,后面实验了下,自己打脸了,SQL 的执行顺序是先分组,后排序

所以我上面的一条SQL 语句期望排序后分组是不现实的。。。

正确的仔细想想后,既然此路不通,那就走别的路

直接来个子查询包一下不就ok了;

SELECT student
FROM (
SELECT * FROM student ORDER BY score DESC
) as tplT GROUP BY uid

其实也是上面的思想,本意就是希望先排好序,然后分组的时候默认第一个就是最值的记录了

但是后面查阅资料的时候发现,这种写法在MySQL 5.6版本以及以下都没问题,但是高点的版本因为会对子查询语句中的排序做优化,直接干掉了,导致子查询没办法返回排序后的临时表。

一种解决方案是通过LIMIT 语句,强行禁止子查询语句的优化

SELECT student
FROM (
SELECT * FROM student ORDER BY score DESC LIMIT 100000(足够大的数,保证解析器能够解析到分组的所有数据进行排序)
) as tplT GROUP BY uid

另一种方式是通过其他的查询方式

通过子查询语句以及数据关联去定位,简单的说就是通过子查询分组查询出最值的字段数据以及分组的字段值去定位外层查询的对象

SELECT *
FROM (
SELECT uid, max(score) as max_score,
FROM student
GROUP BY uid // 根据uid 分组,查询出uid组内的最值
) AS t1 , studnet t2 WHERE t1.uid = t2.uid AND t1.max_score = t2.score

但是这种方式对于分数相同的组内两条数据而言需要怎么抉择就显得比较鸡肋,这种方式的话如果分组后有两条数据并列作为最值,外层查询都会查询出来。

发表评论

电子邮件地址不会被公开。 必填项已用*标注