MySQL高级--14--group by 分组取时间最新的一条数据

news2024/11/26 15:45:36

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • group by 分组取时间最新的一条数据
    • 数据准备
    • 错误查询分析
        • 错误原因
        • 解决思路:
    • 实现方法一(使用 LIMIT 查询)
    • 实现方法二(使用 DISTINCT 查询)
    • 实现方法三(使用 MAX(id) 查询,只适用于自增ID和创建时间排序一致,查询性能最优)
        • 错误查询
    • 性能比对和优化
        • 方法一查询耗时测试和优化
        • 方法二查询耗时测试和优化
        • 方法三查询耗时测试和优化
    • 实现方法四 使用ROW_NUMBER()窗口函数,不允许重复


group by 分组取时间最新的一条数据

  • 在写报表功能时遇到一个需要根据用户id分组查询最新一条钱包明细数据的需求,在写sql测试时遇到一个有趣的问题,开始使用子查询根据时间倒序+group by customer_id发现查询出来的数据一直都是最旧的一条,而不是我需要的最新一条数据我明明已经倒序排了,后来总结出了两种比较完善的解决方案如下。

数据准备

DROP TABLE IF EXISTS `customer_wallet_detail`;
CREATE TABLE `customer_wallet_detail`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `customer_id` bigint(20) NULL DEFAULT NULL COMMENT '用户ID',
  `happen_amount` varchar(15)  NULL DEFAULT '0' COMMENT '发生金额 带-号的代表扣款',
  `balance_amount` varchar(15) NULL DEFAULT '0' COMMENT '可用余额',
  `create_time` bigint(20) NULL DEFAULT NULL COMMENT '发生时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB COMMENT = '用户钱包明细';

INSERT INTO `customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `create_time`) VALUES (1, 1, '100', '100', 1670300656630);
INSERT INTO `customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `create_time`) VALUES (2, 1, '-10', '90', 1670300656640);
INSERT INTO `customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `create_time`) VALUES (3, 1, '5', '95', 1670300656650);
INSERT INTO `customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `create_time`) VALUES (4, 3, '998', '998', 1670300656660);
INSERT INTO `customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `create_time`) VALUES (5, 3, '-100', '898', 1670300656670);
INSERT INTO `customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `create_time`) VALUES (6, 3, '-98', '800', 1670300656680);
INSERT INTO `customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `create_time`) VALUES (7, 2, '666', '666', 1670300656690);
INSERT INTO `customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `create_time`) VALUES (8, 2, '-66', '600', 1670300656695);
INSERT INTO `customer_wallet_detail`(`id`, `customer_id`, `happen_amount`, `balance_amount`, `create_time`) VALUES (9, 2, '-600', '0', 1670300656699);


在这里插入图片描述

错误查询分析

SELECT
	* 
FROM
	( SELECT * FROM customer_wallet_detail ORDER BY create_time DESC ) t1 
GROUP BY
	t1.customer_id;

在这里插入图片描述

错误原因

在这里插入图片描述
在这里插入图片描述

  • 在结果2中可以查看被优化后的语句,我精简了一下优化后的SQL语句会变成这样select * from customer_wallet_detail group by customer_id;,我们可以看到两条语句被合并成了一条,排序没了。
解决思路:
  • 如果想要在分组前排序只要打破MySQL语句优化就行,可以通过LIMIT、DISTINCT、MAX()
    等操作实现,下面会给出三种实现方法。

实现方法一(使用 LIMIT 查询)

  • 鉴于以上的原因我们可以添加上 LIMIT 条件来实现功能,子查询使用分页查询后,MySQL语句优化器就不会再去将两条语句合并了,逻辑不同,所以这里子查询排序会生效。
  • PS:这个LIMIT的数量可以先自行 COUNT 出你要遍历的数据条数(这个数据条数是所有满足查询条件的数据合,我这里共9条数据)
    在这里插入图片描述

实现方法二(使用 DISTINCT 查询)

使用 DISTINCT 查询进行去重的主要原理是通过先对要进行去重的数据进行分组操作,然后从分组后的每组数据中去一条返回给客户端,MySQL语句优化器会认为子查询中进行的其它处理无法合并,查看执行计划和优化后的语句还是和原语句一致,会先执行子查询然后再执行分组查询。

在这里插入图片描述

实现方法三(使用 MAX(id) 查询,只适用于自增ID和创建时间排序一致,查询性能最优)

  • 使用MAX(id)+分组查询可以查询出每组中最大的id,然后通过每组最大数据id集合关联查出数据即可,因为我这里的业务数据是有序插入的,使用主键自增id和create_time结果是一样的而且使用id查询效率更高,如果没有唯一且有序的id可以替代create_time那么就用上面两个方法。

PS:这里使用内连接查询而不使用 IN 查询是因为我测试时发现连接查询会比 IN 查询性能要高50%以上,这个和底层查询机制有关有兴趣可以查看 IN 查询和连接查询的执行计划。

在这里插入图片描述

错误查询

在这里插入图片描述

性能比对和优化

1、准备100w测试数据

# 创建表
DROP TABLE IF EXISTS `customer_wallet_detail_test`;
CREATE TABLE `customer_wallet_detail_test`  (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `customer_id` bigint(20) NULL DEFAULT NULL COMMENT '用户ID',
  `happen_amount` varchar(15)  NULL DEFAULT '0' COMMENT '发生金额 带-号的代表扣款',
  `balance_amount` varchar(15) NULL DEFAULT '0' COMMENT '可用余额',
  `create_time` bigint(20) NULL DEFAULT NULL COMMENT '发生时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB COMMENT = '用户钱包明细';

## 创建一个插入数据的存储过程
DROP PROCEDURE IF EXISTS insert_procedure;
delimiter;;
CREATE PROCEDURE insert_procedure () 
BEGIN
  # 定义循环值
  DECLARE i INT DEFAULT 1;
  #定义一个错误的变量,类型是整形,默认是0
  DECLARE t_error INTEGER DEFAULT 0;
  #捕获到sql的错误,就设置t_error为1
  DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET t_error=1;
  # 开启事务
  START TRANSACTION;
  # 开始循环插入
  WHILE ( i <= 1000000 ) DO
		INSERT INTO `customer_wallet_detail_test`(`customer_id`, `happen_amount`, `balance_amount`, `create_time`) VALUES (CEIL(RAND() * 1000), CEIL(RAND() * 1000), CEIL(RAND() * 1000), UNIX_TIMESTAMP() * 1000);
    SET i = i + 1;
  END WHILE;

  #如果捕获到错误
  IF t_error=1 THEN
    #回滚
    ROLLBACK;
  ELSE
    #提交
    COMMIT;
  END IF;
END;;
delimiter;

# 调用存储过程插入数据
CALL insert_procedure ();

方法一查询耗时测试和优化

在这里插入图片描述

方法二查询耗时测试和优化

在这里插入图片描述

方法三查询耗时测试和优化

在这里插入图片描述
结合我的业务经过测试,目前看来方法三是最合适的,性能较高,方案一和方案二性能较差,最终选择那个方案主要看业务而定,而且这里查询都是没有where条件,在添加上where条件并且附加上辅助查询的索引后,查询耗时会有很大变化,结合业务选择一种方法即可。

实现方法四 使用ROW_NUMBER()窗口函数,不允许重复

  • 这个函数可以Oracle中使用
  • 这个函数可以hive可以用
  • MySQL5.7用不了,MySQL8以后加入了窗口函数

sql函数–04—ROW_NUMBER() OVER()函数用法详解

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1590939.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电子章是怎么盖上去的?

电子章是怎么盖上去的呢&#xff0c;本文介绍利e-章宝(易友EU3000智能盖章软件)盖电子骑缝章的方法。如下&#xff1a; 1.在软件中导入待批量盖章的PDF文件 如下图&#xff0c;在“待盖章PDF文件”区域&#xff0c;点“添加”&#xff0c;导入待盖章PDF文件。 如上图&#xf…

Linux第89步_了解异步通知及其结构和函数

1、了解“异步通知” “异步通知”的核心就是信号。信号是采用软件模拟的“中断”&#xff0c;它由“驱动程序”主动向“应用程序”发送信号&#xff0c;并报告自己可以访问了&#xff0c;“应用程序”收到信号以后&#xff0c;就从“驱动设备”中读取或者写入数据。整个过程就…

npm install 报 ERESOLVE unable to resolve dependency tree 异常解决方法

问题 在安装项目依赖时&#xff0c;很大可能会遇到安装不成功的问题&#xff0c;其中有一个很大的原因&#xff0c;可能就是因为你的npm版本导致的。 1.npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree 2.ERESOLVE unable to resolve dependenc…

赋能未来:AI技术革新中的创业契机

目录 前言 一、行业解决方案 1、行业参考说明 2、操作步骤建议 二、智能产品和服务 1、行业参考说明 2、操作步骤建议 三、教育和培训 1、行业参考说明 2、操作步骤建议 总结 前言 随着人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;越来越多的创业…

高质量ChatGPT Prompts 精选

通用超级 Prompt GPT4实用。通用超级 prompt &#xff0c;根据你想要的输出和你的反馈&#xff0c;自动使用相应的专家角色帮你解决问题。如果需要升级ChatGPT Plus&#xff0c;可以参考教程 升级 GPT4.0 保姆教程 您是一位具有多领域专长的专家级ChatGPT提示工程师。在我们…

IP证书申请流程

目录 域名与IP的关系 SSL证书绑定域名还是绑定IP&#xff1f; IP证书支持免费申请吗&#xff1f; 如何申请IP地址证书 IP类型的SSL证书&#xff0c;又称之为IP SSL&#xff0c;这种SSL证书是专门用于公网IP地址验证的一种数字证书。 主要功能就是解决IP地址明文传输的安全…

【JAVA基础篇教学】第八篇:Java中List详解说明

博主打算从0-1讲解下java基础教学&#xff0c;今天教学第八篇&#xff1a;Java中List详解说明。 在 Java 编程中&#xff0c;List 接口是一个非常常用的集合接口&#xff0c;它代表了一个有序的集合&#xff0c;可以包含重复的元素。List 接口提供了一系列操作方法&#xff0c;…

Pytorch: 利用预训练的残差网络ResNet50进行图像特征提取,并可视化特征图热图

1. 残差网络ResNet的结构 2.图像特征提取和可视化分析 import cv2 import time import os import matplotlib.pyplot as plt import torch from torch import nn import torchvision.models as models import torchvision.transforms as transforms import numpy as npimgname…

Windows 2003 R2与Windows 2022建立域信任报错:本地安全机构无法跟域控制器获得RPC连接。请检查名称是否可以解析,服务器是否可用。

在Windows Server 2003 R2与Windows Server 2022之间建立域信任时遇到“本地安全机构无法与域控制器获得RPC连接”的错误&#xff0c;可能是由于以下几种原因&#xff1a; DNS 解析问题&#xff1a; 确保源域和目标域的DNS配置正确&#xff0c;能够互相解析对方的域名和IP地址。…

Kubernetes学习笔记12

k8s核心概念&#xff1a;控制器&#xff1a; 我们删除Pod是可以直接删除的&#xff0c;如果生产环境中的误操作&#xff0c;Pod同样也会被轻易地被删除掉。 所以&#xff0c;在K8s中引入另外一个概念&#xff1a;Controller&#xff08;控制器&#xff09;的概念&#xff0c;…

搭建个人智能家居 4 -WS2812B-RGB灯

搭建个人智能家居 4 - WS2812B-RGB灯 前言说明ESPHomeHomeAssistant 前言 上一篇文章我们已经完成了第一个外设的添加&#xff08;一个LED灯&#xff09;&#xff0c;今天接着来“壮大”这个系统&#xff0c;添加第二个外设“RGB灯”。 环境搭建可以回顾前面的文章。前文回顾&…

界面控件DevExtreme JS ASP.NET Core 2024年度产品规划预览(二)

在本文中我们将介绍今年即将发布的v24.1附带的主要特性&#xff0c;这些特性既适用于DevExtreme JavaScript (Angular、React、Vue、jQuery)&#xff0c;也适用于基于DevExtreme的ASP.NET MVC/Core控件。 注意&#xff1a;本文中列出的功能和特性说明官方当前/预计的发展计划&a…

PrimeKG:为精准医学分析设计的多模态知识图谱

PrimeKG&#xff1a;为精准医学分析设计的多模态知识图谱 PrimeKG简介数据资源和覆盖范围构建方法和技术细节PrimeKG多模态知识图谱的概览构建PrimeKG的过程PrimeKG 数据 多模态特性和临床应用PrimeKG 设计逻辑 论文&#xff1a;https://www.nature.com/articles/s41597-023-01…

盘点“整容”成功的国漫男主,唐三萧炎谁才是顶级颜值?

国漫男主千千万&#xff0c;可不是每一位都能做到颜值与实力并存&#xff01;有些男性角色的建模起初受限于技术和审美等原因&#xff0c;呈现出的效果并不理想&#xff0c;好在越来越多的作品开始尝试给角色模型更新换代&#xff0c;本期为您盘点那些成功更换模型的国漫男主&a…

Acrobat Pro DC 2023 for mac直装激活版 pdf编辑处理工具

Acrobat Pro DC 2023 for Mac是一款功能强大的PDF编辑器&#xff0c;为用户提供了全面且高效的PDF处理体验。 软件下载&#xff1a;Acrobat Pro DC 2023 for mac直装激活版下载 首先&#xff0c;它支持用户从现有文档创建PDF&#xff0c;或者将其他文件格式如图片、网页等轻松转…

【fastapi】搭建第一个fastapi后端项目

本篇文章介绍一下fastapi后端项目的搭建。其实没有什么好说的&#xff0c;按照官方教程来即可&#xff1a;https://fastapi.tiangolo.com/zh/ 安装依赖 这也是我觉得python项目的槽点之一。所有依赖都安装在本地&#xff0c;一旦在别人电脑上编写项目就又要安装一遍。很扯淡。…

JavaSEhomework2

题目&#xff0c;上图&#xff01;&#xff01; 上代码 import java.util.Scanner; public class homework01 {public static void main(String[] args) {Scanner input new Scanner(System.in);System.out.print("Enter the number of values: ");int num input.…

MySQL 表管理

目录 建库 语法&#xff1a; 库名命名规则&#xff1a; 相关命令&#xff1a; 建表 语法&#xff1a; 相关命令&#xff1a; 修改表 语法&#xff1a; 常用操作命令 复制表 数据类型 MySQL的10种常用数据类型&#xff1a; 数据的导入和导出 导入&#xff1a; 格…

CSS特效---HTML+CSS实现3D旋转卡片

1、演示 2、一切尽在代码中 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document</title&…

MongoDB爬虫:(某扑)实战

https://bbs.hupu.com/bxj网页地址: https://bbs.hupu.com/bxj 然后我们在网页上定义帖子名称、帖子链接、创建时间、回复数、最后回复用户...... 除此之外,我们发现虎扑步行街最多显示的页数(20): 、 当我们打开第3页的时候,网页的URL的地址变为了:https://bbs.hupu.…