mysql分组后获取每个组排序后的第一条数据(整行)

https://blog.csdn.net/persistencegoing/article/details/92764058

All rights reserved.No part of this article may be reproduced or distributed by any means,or stored in a database or retrieval system,without the prior written permission of persistenceGoing author
https://blog.csdn.net/persistencegoing/article/details/84376427

有一个学生分数表student,数据结构是这样的

id(当前表ID)    student_id(学生ID)    line(分数)   subject_type(科目类型)

1                           1                             80                       1

2                           1                             78                       1

3                           1                             56                       1

4                           2                             99                       1

5                           2                             20                       1

我想根据学生分组  ,得到每个分组中分数最高的那一条数据:

先来几种错误的写法:
(1)SELECT
    max.*, MAX(max.line) lineMax
FROM
    (SELECT * FROM student) max
GROUP BY
    student_id

这种写法你会发现line和lineMax的列中数据可能不一致

(2)SELECT
    max.*, MAX(max.line) lineMax
FROM
    (
        SELECT
            *
        FROM
            student
        ORDER BY
            line DESC
    ) max
GROUP BY
    student_id

你可能会说排序之后再分组就对了,抱歉,这种情况下对于某些小伙伴可能还是会有问题

(3)SELECT
    max.*, MAX(max.line) lineMax
FROM
    (
        SELECT
            *
        FROM
            student
        ORDER BY
            line DESC
    ) max
GROUP BY
    student_id
HAVING lineMax=line

这种情况下,表面上数据是对的,但是数据量大了之后你会发现有些数据丢失,其实还是错的

正确写法:
SELECT
    max.*, MAX(max.line) lineMax
FROM
    (
        SELECT
            *
        FROM
            student 
        ORDER BY
            line DESC
    LIMIT 100
    ) max
GROUP BY
    student_id

在mysql5.7版本之后,必须再排序之后加上limit关键字,20万所测试的数据是正确的,亲测验证

注意: 
limit 是必须要加的,如果不加的话,数据不会先进行排序,通过 explain 查看执行计划,可以看到没有 limit 的时候,少了一个 DERIVED 操作。

可用以下SQL对每组数据进行验证

SELECT
    *
FROM
    student
WHERE
    student_id = 69
ORDER BY
    line DESC
LIMIT 100

————————————————
版权声明:本文为CSDN博主「persistenceヾ(?°∇°?)?」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/persistencegoing/article/details/92764058

原文地址:https://www.cnblogs.com/rxbook/p/12092321.html

时间: 2024-08-06 00:43:33

mysql分组后获取每个组排序后的第一条数据(整行)的相关文章

Oracle分组取第一条数据

看看以前的私密日志,原来自己之前被很多小而简单的问题困惑过! 看着那时候我们还是新手中的新手做的备忘笔记! 其实就是用了Oracle的统计函数而已! 以前的日记(看样子应该是以前公司的源码,呵呵--)如下:勿喷! 对多数据进行分组排序后取每组第一条记录: SELECT * FROM ( SELECT ROW_NUMBER() OVER( PARTITION BY ZA40011_3.URIAGE_DENPYO_NO,ZA40011_3.URIAGE_DENPYO_ROW_NO ORDER BY

sql分组取第一条数据

sq分组取第一条数据的一个方法: select * from ( select row_number() over(partition by ID order by ID) as rownum , * from table ) as temp where temp.rownum = 1

oracle分组后取每组第一条数据

数据格式: 分组取第一条的效果: sql语句: SELECT * FROM ( SELECT ROW_NUMBER() OVER(PARTITION BY x ORDER BY y DESC)rn, test1.* FROM test1) WHERE rn = 1 ;

mysql分组查询获取组内某字段最大的记录

id sid cid 1 1 12 1 23 2 1 以sid分组,最后取cid最大的那一条,以上要取第2.3条 1 方法一: 2 select * from (select * from table order by cid desc) as a group by a.sid 3 4 方法二: 5 select a.* from table as a where cid = (select max(cid) from table where a.sid = sid) 6 7 方法三: 8 se

SQL 分组(分区)排序获取第一条数据 ROW_NUMBER() OVER() PARTITION BY的使用

将最近用到的一些sql 记录下来 首先来看下应用场景: 有一张价格 "订单价格设置" 表如下: 商品编号,价格设置时间id(类似于创建时间,创建时间约早,则act_id越小) ,价格的时间段,商品价格 现在要求选出每个商品价格最大,价格设置时间id最大的那条记录,要求先考虑价格,再考虑设置时间 理想的结果:取出的是第3条记录 和第5条记录 思路:将数据根据item分区,再在每个分区中进行排序,先根据价格排序,再根据设置时间id排序,最后取出每个分组的第一条记录 实现: 利用 ROW_N

c# 对List<T> 某字段排序,取TOP条数据

//排序的对象里的字段数据准备 try { cmr.v4 = Double.Parse(cmr.v3) - Double.Parse(cmr.v2); } catch (Exception e) { }  cmjList.Add(cmr); //建立临时List<T> List<CModelJunction> cmjList_showtab = new List<CModelJunction>();//用于显示在右上表格中的junction 100条 //排序后取TOP

MySQL获取group后所有组的第一条数据

https://stackoverflow.com/a/28090544/8025086 https://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/ 原文地址:https://www.cnblogs.com/buxizhizhoum/p/10658122.html

mysql或者oracle分组排序取前几条数据

mysql: select a.* from(select t1.*,(select count(*)+1 from 表 where 分组字段=t1.分组字段 and 排序字段<t1.排序字段) as group_idfrom 表 t1) awhere a.group_id<=3 Oracle: SELECT t.*            FROM (SELECT ROW_NUMBER() OVER(PARTITION BY 分组字段 ORDER BY 排序字段 DESC) rn,      

oracle分组取每组第一条数据

select * from test; no time name 1001   20141226 zhangsan 1001   20141227 lisi 1002 20141228 wangwu 1002  20141229 zhaoliu select * from (select rank() over(partition by documentno order by time desc) r,a.* from test a) where r=1; no time