Mysql分组查询取最新的几种方案总结

 更新时间:2023年05月27日 11:51:47   作者:lianshanchi  
在写报表功能时遇到一个需要根据用户id分组查询最新一条钱包明细数据的需求,下面这篇文章主要给大家总结介绍了关于Mysql分组查询取最新的几种方案,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

1.row_number函数 (mysql8以上支持)

示例:

SELECT *
FROM
( SELECT *, row_number ( ) over ( PARTITION BY 分组字段 ORDER BY 排序字段 DESC ) AS rn FROM 表 ) pca
WHERE
pca.rn = 1

解释:

1. rn字段:返回的是分组内的结果排序依次递增

2. 分组字段:进行分组的字段

3. 排序字段:需要取最新逻辑的字段

注意:

row_number函数得到的字段rn不能在表后面直接加where条件过滤,需要用select包装生成临时表pca 再进行取最新过滤
并且该函数只能在mysql8.0版本以上运行,5.7不支持该函数

2.子查询

示例:

SELECT *
FROM
表 a
WHERE
a.排序字段 = ( SELECT max( b.排序字段 ) FROM 表 b WHERE b.分组字段 = a.分组字段 )
GROUP BY
a.分组字段

解释:

分组字段:进行分组的字段排序字段:严格意义上不叫排序字段,可以在当前sql语句中可以认为是在分组后需要找最新值字段

注意:

该子查询性能属于四种方案中最低,不适合大数据量查询使用,

最后GROUP BY分组字段是为了在多个最大值有多个相同数据情况下去重处理 按业务场景可去掉

3.临时表

示例:

创建临时表
CREATE TEMPORARY TABLE tmp_表 as select 分组字段,max(排序字段)as 排序字段 from 表 group by 排序字段;
关联临时表查询
select * from 表 p join tmp_表 tmp on tmp.分组字段= p.分组字段 and tmp.排序字段= p.排序字段

解释:

分组字段:进行分组的字段

排序字段:严格意义上不叫排序字段,可以在当前sql语句中可以认为是在分组后需要找最新值字段

注意:

先查询出最新的结果存入临时表,再进行联表查询,数据量大一点的情况下 可以对创建完的临时表加索引,使整个过程的复杂度趋近f(n)。

4.新增字段标识

从业务层面优化,在表上加一个字段,isnewdata,bit型或者int型就好,每次在表中提交数据时,事务中先将要提交的数据所涉及的id,将历史数据isnewdata=1的更新为0,新提交的数据,isnewdata为1,然后增加一个索引isnewdata,或者如果需要和其他表关联的时候,增加复合索引,性能一下就上来了。

5.使用mysql用户变量提供排序序列号

示例:

SET @rank := 0;
SET @cgroup := NULL;
SELECT
a.*
IF
( @cgroup = a.分组字段, @rank := @rank + 1, @rank := 1 ) AS rank_no,
@cgroup := a.分组字段,
FROM
表 a
ORDER BY
a.分组字段,
a.排序字段 ASC

解释:

分组字段:进行分组的字段
排序字段:分组后排序的字段
@rank :序号计数变量
@cgroup :分组字段暂存变量,用来比较是否进入了下一组数据

运行逻辑:

该sql首先会进行排序,先分组字段,再排序字段,这点很关键,然后根据mysql的service层执行顺序对展示数据进行处理,先进入if函数判断数据是累加还是初始化@rank用户变量(注意首先第一次进来@cgroup为空),然后将分组字段的值赋予@cgroup变量。整个执行过程非常精巧有意思,得细细品味。

注意:

不支持开窗函数的mysql版本可以使用该方式,但是要ORM支持多行SQL代码块才行,还要修改数据库的SQL_MODE,mybatis和JPA都可以,Oracle不行 需要配置。比如mycat这种数据库中间件

附:MySQL 取出每个分组中最新的一条数据(ID最大)

场景:由于一个摄像头管理一个范围,且管理的某个人可以多次犯规。故,一个摄像头可以上报有多个事件,多个事件可能同时上报,可能有先后顺序。

需求:现地图只显示有事件摄像头的最新一条事件信息,故,需要ID倒序后,以摄像头分组,以此获得摄像头最新的一条事件信息。(这里以ID倒序而不以创建时间倒序,是有一定优势的)。

思路:先ID(时间)倒序,后分组。

说明:  如果是单表查询,默认分组后是ID最大的一条数据,若是连表查询,需要以下方法处理。

SELECT t.id,t.camera_id,t.create_time FROM 
    (SELECT e.* FROM sys_enforce_event e LEFT JOIN sys_dict_node n ON e.node_id = n.id 
    WHERE e.is_deleted = 0 AND e.source_id = 2 AND n.`code` IN (200,301,302,400,500) AND e.camera_id IS NOT NULL ORDER BY e.id DESC ) t    
GROUP BY t.camera_id 

以下方式就不对了,查找的不是最新一条记录(连表查询,看清区别)

SELECT e.* (SELECT * FROM sys_enforce_event ORDER BY id DESC ) e LEFT JOIN sys_dict_node n ON e.node_id = n.id
    WHERE e.is_deleted = 0 AND e.source_id = 2 AND n.`code` IN (200,301,302,400,500 ) AND e.camera_id IS NOT NULL     
GROUP BY e.camera_id 

注意事项:此方式仅支持低于5.7版本的MySql(SELECT VERSION();)

关于高于5.7版本的,可在排序后添加l imit 999999,即可为最新一条。

总结:

如果业务数据量不大,最多就几万条,用方案1,2,3均可。数据量不超过100万行,方案1和3还能勉强顶住。超过100万行,就要从业务层面去优化了,此时选择方案4是明智的

到此这篇关于Mysql分组查询取最新的几种方案总结的文章就介绍到这了,更多相关Mysql分组查询取最新内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Win10 64位使用压缩包安装最新MySQL8.0.18的教程(图文详解)

    Win10 64位使用压缩包安装最新MySQL8.0.18的教程(图文详解)

    本文通过图文并茂的形式给大家介绍了WIN10 64位使用压缩包安装最新MySQL8.0.18的教程,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-12-12
  • 为什么MySQL不建议使用SELECT *

    为什么MySQL不建议使用SELECT *

    这篇文章主要介绍了为什么MySQL不建议使用SELECT *,不要使用SELECT *”几乎已经成为了MySQL使用的一条金科玉律,下面文章我们就来看看具体的原因,需要的朋友可以参考一下
    2022-04-04
  • 详解MySQL中事务隔离级别的实现原理

    详解MySQL中事务隔离级别的实现原理

    这篇文章主要介绍了MySQL中事务隔离级别的实现原理,帮助大家更好的理解和使用MySQL数据库,感兴趣的朋友可以了解下
    2021-01-01
  • MySQL几种更新操作的案例分析

    MySQL几种更新操作的案例分析

    本文将通过一个用户账户金额更新的案例分析几种数据更新的操作的优劣,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • MySQL中in和exists区别详解

    MySQL中in和exists区别详解

    最近在写SQL语句时,对选择IN 还是Exists犹豫不决,所以就上网查询了一下资料,本文就详细的介绍了两个方法的区别,感兴趣的可以了解一下
    2021-06-06
  • Windows服务器MySQL中文乱码的解决方法

    Windows服务器MySQL中文乱码的解决方法

    这篇文章主要介绍了MySQL中文乱码的一些解决方案,本文同时分解了MySQL中文乱码的原因分析,需要的朋友可以参考下
    2015-01-01
  • mysql批量插入BulkCopy的实现

    mysql批量插入BulkCopy的实现

    本文主要介绍了mysql批量插入BulkCopy的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • MySQL5.7如何修改root密码

    MySQL5.7如何修改root密码

    这篇文章主要为大家详细介绍了MySQL5.7修改root密码的相关方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • 将MySQL数据库移植为PostgreSQL

    将MySQL数据库移植为PostgreSQL

    PostgreSQL 作为功能最强劲的开源 OO 数据库,仿佛一直不为国内用户所熟识。而我个人也仅是因为工作的缘故接触到这款超经典的数据库,并深为之折服。
    2009-07-07
  • 一文详解MYSQL最朴素的监控方式

    一文详解MYSQL最朴素的监控方式

    对于当前数据库的监控方式有很多,分为数据库自带、商用、开源三大类,每一种都有各自的特色,那我们今天就介绍一下完全采用mysql自有方式采集获取监控数据,在单体下达到最快速、方便、损耗最小,感兴趣的同学可以借鉴阅读
    2023-05-05

最新评论