MySQL分组,获取组内最新的10条数据

一、记录

记录一次SQL,最近在项目中遇到了一个相对比较复杂的SQL。
要求依据分组,获取每个分组后的前10条数据。
分组查询最新的数据,应该都做过,但是获取前10条数据,还是没处理过的。

二、处理

2.1 前期数据准备

新建一个测试表

CREATE TABLE `t_user` (`ID` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`ACCOUNT` varchar(50) DEFAULT NULL COMMENT '账号',`NAME` varchar(50) DEFAULT NULL COMMENT '姓名',`TIME` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '时间',PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='测试表';

搞一批测试数据

INSERT INTO `t_user` (`ACCOUNT`, `NAME`, `TIME`) VALUES 
('zhangsan', '张三', '2024-01-01 00:00:00'),
('zhangsan', '张三', '2024-01-02 00:00:00'),
('zhangsan', '张三', '2024-01-03 00:00:00'),
('zhangsan', '张三', '2024-01-04 00:00:00'),
('zhangsan', '张三', '2024-01-05 00:00:00'),
('zhangsan', '张三', '2024-01-06 00:00:00'),
('zhangsan', '张三', '2024-01-07 00:00:00'),
('zhangsan', '张三', '2024-01-08 00:00:00'),
('zhangsan', '张三', '2024-01-09 00:00:00'),
('zhangsan', '张三', '2024-01-10 00:00:00'),
('zhangsan', '张三', '2024-01-11 00:00:00'),
('lisi', '李四', '2024-01-01 00:00:00'),
('lisi', '李四', '2024-01-02 00:00:00'),
('lisi', '李四', '2024-01-03 00:00:00'),
('lisi', '李四', '2024-01-04 00:00:00'),
('lisi', '李四', '2024-01-05 00:00:00'),
('lisi', '李四', '2024-01-06 00:00:00'),
('lisi', '李四', '2024-01-07 00:00:00'),
('lisi', '李四', '2024-01-08 00:00:00'),
('lisi', '李四', '2024-01-09 00:00:00'),
('lisi', '李四', '2024-01-10 00:00:00'),
('lisi', '李四', '2024-01-11 00:00:00'),
('wangwu', '王五', '2024-01-01 00:00:00'),
('wangwu', '王五', '2024-01-02 00:00:00'),
('wangwu', '王五', '2024-01-03 00:00:00'),
('wangwu', '王五', '2024-01-04 00:00:00'),
('wangwu', '王五', '2024-01-05 00:00:00'),
('wangwu', '王五', '2024-01-06 00:00:00'),
('wangwu', '王五', '2024-01-07 00:00:00'),
('wangwu', '王五', '2024-01-08 00:00:00'),
('wangwu', '王五', '2024-01-09 00:00:00'),
('wangwu', '王五', '2024-01-10 00:00:00'),
('wangwu', '王五', '2024-01-11 00:00:00');

数据如图,进行SQL验证

在这里插入图片描述

2.2 SQL

1、根据账号分组,时间倒叙排序,查询前10条数据

-- 根据账号分组,时间倒叙排序,查询前10条数据
SELECT t_all.* FROM (
SELECT (@s:=@s+1) AS t_id, t.* FROM t_user t, (SELECT @s:=0) t_table ORDER BY ACCOUNT, TIME ASC 
) t_all
INNER JOIN (SELECT max(s_id) s_id, ACCOUNT FROM (SELECT (@i:=@i+1) AS s_id, s.* FROM t_user s, (SELECT @i:=0) s_table ORDER BY ACCOUNT, TIME ASC ) tmp GROUP BY ACCOUNT
) s_all ON t_all.ACCOUNT = s_all.ACCOUNT AND t_all.t_id > s_all.s_id - 10
ORDER BY t_all.ACCOUNT, t_all.TIME DESC;

得到结果如下,没有出现 1 号的数据,说明SQL可用。
在这里插入图片描述

2.3 延伸

从上面的SQL可以看出来,是以一个基数,然后去截取前10个来做的。
这样的话,我们其实可以变更一下需求,将SQL改写一下。
即:
根据账号分组,时间倒叙排序,查询前10条数据中的,第1条数据。

第一条数据SQL如下:

-- 根据账号分组,时间倒叙排序,查询前10条数据中的第一条数据
SELECT t_all.* FROM (
SELECT (@s:=@s+1) AS t_id, t.* FROM t_user t, (SELECT @s:=0) t_table ORDER BY ACCOUNT, TIME ASC 
) t_all
INNER JOIN (SELECT max(a_id) a_id, ACCOUNT FROM (SELECT (@a:=@a+1) AS a_id, a.* FROM t_user a, (SELECT @a:=0) a_table ORDER BY ACCOUNT, TIME ASC ) tmp GROUP BY ACCOUNT
) a_all ON t_all.ACCOUNT = a_all.ACCOUNT AND t_all.t_id > a_all.a_id - 1
INNER JOIN (SELECT max(b_id) b_id, ACCOUNT FROM (SELECT (@b:=@b+1) AS b_id, b.* FROM t_user b, (SELECT @b:=0) b_table ORDER BY ACCOUNT, TIME ASC ) tmp GROUP BY ACCOUNT
) b_all ON t_all.ACCOUNT = b_all.ACCOUNT AND t_all.t_id < b_all.b_id + 1
ORDER BY t_all.ACCOUNT, t_all.TIME DESC;

那么以此类推,第二条数据:

-- 根据账号分组,时间倒叙排序,查询前10条数据中的第二条数据
SELECT t_all.* FROM (
SELECT (@s:=@s+1) AS t_id, t.* FROM t_user t, (SELECT @s:=0) t_table ORDER BY ACCOUNT, TIME ASC 
) t_all
INNER JOIN (SELECT max(a_id) a_id, ACCOUNT FROM (SELECT (@a:=@a+1) AS a_id, a.* FROM t_user a, (SELECT @a:=0) a_table ORDER BY ACCOUNT, TIME ASC ) tmp GROUP BY ACCOUNT
) a_all ON t_all.ACCOUNT = a_all.ACCOUNT AND t_all.t_id > a_all.a_id - 2
INNER JOIN (SELECT max(b_id) b_id, ACCOUNT FROM (SELECT (@b:=@b+1) AS b_id, b.* FROM t_user b, (SELECT @b:=0) b_table ORDER BY ACCOUNT, TIME ASC ) tmp GROUP BY ACCOUNT
) b_all ON t_all.ACCOUNT = b_all.ACCOUNT AND t_all.t_id < b_all.b_id 
ORDER BY t_all.ACCOUNT, t_all.TIME DESC;

第三条数据:

-- 根据账号分组,时间倒叙排序,查询前10条数据中的第三条数据
SELECT t_all.* FROM (
SELECT (@s:=@s+1) AS t_id, t.* FROM t_user t, (SELECT @s:=0) t_table ORDER BY ACCOUNT, TIME ASC 
) t_all
INNER JOIN (SELECT max(a_id) a_id, ACCOUNT FROM (SELECT (@a:=@a+1) AS a_id, a.* FROM t_user a, (SELECT @a:=0) a_table ORDER BY ACCOUNT, TIME ASC ) tmp GROUP BY ACCOUNT
) a_all ON t_all.ACCOUNT = a_all.ACCOUNT AND t_all.t_id > a_all.a_id - 3
INNER JOIN (SELECT max(b_id) b_id, ACCOUNT FROM (SELECT (@b:=@b+1) AS b_id, b.* FROM t_user b, (SELECT @b:=0) b_table ORDER BY ACCOUNT, TIME ASC ) tmp GROUP BY ACCOUNT
) b_all ON t_all.ACCOUNT = b_all.ACCOUNT AND t_all.t_id < b_all.b_id - 1
ORDER BY t_all.ACCOUNT, t_all.TIME DESC;

第四条数据:

-- 根据账号分组,时间倒叙排序,查询前10条数据中的第四条数据
SELECT t_all.* FROM (
SELECT (@s:=@s+1) AS t_id, t.* FROM t_user t, (SELECT @s:=0) t_table ORDER BY ACCOUNT, TIME ASC 
) t_all
INNER JOIN (SELECT max(a_id) a_id, ACCOUNT FROM (SELECT (@a:=@a+1) AS a_id, a.* FROM t_user a, (SELECT @a:=0) a_table ORDER BY ACCOUNT, TIME ASC ) tmp GROUP BY ACCOUNT
) a_all ON t_all.ACCOUNT = a_all.ACCOUNT AND t_all.t_id > a_all.a_id - 4
INNER JOIN (SELECT max(b_id) b_id, ACCOUNT FROM (SELECT (@b:=@b+1) AS b_id, b.* FROM t_user b, (SELECT @b:=0) b_table ORDER BY ACCOUNT, TIME ASC ) tmp GROUP BY ACCOUNT
) b_all ON t_all.ACCOUNT = b_all.ACCOUNT AND t_all.t_id < b_all.b_id - 2
ORDER BY t_all.ACCOUNT, t_all.TIME DESC;

三、总结

从上述SQL可以看出:

查询前10条数据,其实就是一个 大于号
而后续的查询前10个数据中的第n条数据,也就是在原先的 大于号 的基础上,进行范围的缩小,增加一个 小于号 ,即通过框定查询结果的范围来得到想要的查询结果,SQL的体现上就是对于 t_id 的范围的框定。

四、其他

对于查询前10条数据中的第n条数据
以下是不同的写法,可以实现同样的效果,但是SQL却略微不同。
感兴趣的老铁可以自行研究研究

-- 根据账号分组,时间倒叙排序,查询前10条数据中的第一条数据
SELECT t_all.* FROM (
SELECT (@s:=@s+1) AS t_id, t.* FROM t_user t, (SELECT @s:=0) t_table ORDER BY ACCOUNT, TIME DESC 
) t_all
INNER JOIN (SELECT max(a_id) a_id, ACCOUNT FROM (SELECT (@a:=@a+1) AS a_id, a.* FROM t_user a, (SELECT @a:=0) a_table ORDER BY ACCOUNT, TIME DESC ) tmp GROUP BY ACCOUNT
) a_all ON t_all.ACCOUNT = a_all.ACCOUNT AND t_all.t_id > a_all.a_id - 11
INNER JOIN (SELECT max(b_id) b_id, ACCOUNT FROM (SELECT (@b:=@b+1) AS b_id, b.* FROM t_user b, (SELECT @b:=0) b_table ORDER BY ACCOUNT, TIME DESC ) tmp GROUP BY ACCOUNT
) b_all ON t_all.ACCOUNT = b_all.ACCOUNT AND t_all.t_id < b_all.b_id - 9
ORDER BY t_all.ACCOUNT, t_all.TIME DESC;-- 根据账号分组,时间倒叙排序,查询前10条数据中的第二条数据
SELECT t_all.* FROM (
SELECT (@s:=@s+1) AS t_id, t.* FROM t_user t, (SELECT @s:=0) t_table ORDER BY ACCOUNT, TIME DESC 
) t_all
INNER JOIN (SELECT max(a_id) a_id, ACCOUNT FROM (SELECT (@a:=@a+1) AS a_id, a.* FROM t_user a, (SELECT @a:=0) a_table ORDER BY ACCOUNT, TIME DESC ) tmp GROUP BY ACCOUNT
) a_all ON t_all.ACCOUNT = a_all.ACCOUNT AND t_all.t_id > a_all.a_id - 10
INNER JOIN (SELECT max(b_id) b_id, ACCOUNT FROM (SELECT (@b:=@b+1) AS b_id, b.* FROM t_user b, (SELECT @b:=0) b_table ORDER BY ACCOUNT, TIME DESC ) tmp GROUP BY ACCOUNT
) b_all ON t_all.ACCOUNT = b_all.ACCOUNT AND t_all.t_id < b_all.b_id - 8
ORDER BY t_all.ACCOUNT, t_all.TIME DESC;

参考链接:https://blog.csdn.net/wang1qqqq/article/details/117603407

OK,就这些吧。

有什么不对的还望指正,书写不易,觉得有帮助就点个赞吧!☺☺☺

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

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

相关文章

开发知识点-Flutter移动应用开发

支持 安卓 IOS Android 鸿蒙 第一章dart基础章节介绍 移动电商——Flutter-广告Banner组件制作 移动电商——Flutter实战课程介绍 Flutter实例——路由跳转的动画效果

Elment UI的el-table-column表头旁边有点击按钮类似的操作

Elment UI的el-table-column表头旁边有点击按钮类似的操作 <el-table-column fixed"right" label"操作" ><!-- 表头 --> {{-- <template slot"header" header"scope">--}} {{-- <span…

精通 VS 调试技巧,学习与工作效率翻倍!

​ ✨✨ 欢迎大家来到贝蒂大讲堂✨✨ ​ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; ​ 所属专栏&#xff1a;C语言学习 ​ 贝蒂的主页&#xff1a;Betty‘s blog 1. 什么是调试 当我们写代码时候常常会遇见输出结果不符合我们预…

单轴测径仪在线缆电缆测控中的应用

线缆电缆在生产中能进行品质测量与控制&#xff0c;对其生产模式而言&#xff0c;是更为合适的&#xff0c;毕竟其生产模式决定了其任何品质问题出现都会造成产品的品质下降或不合格。要想进行生产高品质的产品&#xff0c;对产线的要求较高。 单轴测径仪作为测控一体&#xff…

安卓开发之自动缩放布局

AutoScalingLayout 适用于 Android 的自动缩放布局。 替换布局&#xff1a; 我们只需要替换根布局所需的自动缩放&#xff0c;子布局也将实现自动缩放。 原始布局AutoScalingLayout相对布局ASRelativeLayout线性布局ASLinearLayoutFrameLayout&#xff08;框架布局&#xff…

项目一:踏上Java开发之旅

文章目录 一、实战概述二、实战步骤任务1&#xff1a;安装配置JDK并开发第一个Java程序步骤一&#xff1a;安装JDK步骤二&#xff1a;配置JDK环境变量步骤三&#xff1a;开发第一个Java程序 课堂练习任务1、打印个人信息任务2、打印直角三角形任务3、打印一颗爱心任务4、打印史…

Linux服务器系统修改SSH端口教程

修改端口号是通过修改SSH的配置文件实现的&#xff0c;在服务器终端先激活root用户&#xff0c;然后输入&#xff1a; vim /etc/ssh/sshd_config找到#Port 22这个位置 键盘按i进入编辑模式 删除掉Port 22前面的#&#xff0c;然后键盘按一下回车键&#xff08;如果没有#可不必…

记一次SPI机制导致的BUG定位【不支持:http://javax.xml.XMLConstants/property/accessExternalDTD】

1、前因 今天在生产环境启用了某个功能&#xff0c;结果发现有个文件上传华为云OBS失败了&#xff0c;报错如下&#xff1a; Caused by: java.lang.IllegalArgumentException: 不支持&#xff1a;http://javax.xml.XMLConstants/property/accessExternalDTDat org.apache.xal…

C++参悟:数值运算相关

数值运算相关 一、概述二、常用数学函数1. 基础运算1. 浮点值的绝对值&#xff08; |x| &#xff09;2. 浮点除法运算的余数3. 除法运算的有符号余数4. 除法运算的有符号余数和最后三个二进制位5. 混合的乘加运算6. 两个浮点值的较大者7. 两个浮点值的较小者8. 两个浮点值的正数…

Grafana loki配置, 无脑版

使用docker部署Grafana loki 1.创建 docker-compose.yml 文件 touch docker-compose.yml写入以下内容 vim touch docker-compose.yml version: "3"networks:loki:services:loki:image: grafana/loki:latestrestart: unless-stoppedports:- "3100:3100"vo…

LeetCode 14.最长公共前缀(python版)

需求 编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀&#xff0c;返回空字符串 “”。 示例 1&#xff1a; 输入&#xff1a;strs [“flower”,“flow”,“flight”] 输出&#xff1a;“fl” 示例 2&#xff1a; 输入&#xff1a;strs [“dog”,“race…

【高效开发工具系列】Intellj IDEA 2023.3 版本

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

curl命令导致你下载的文件为空原因分析

文章目录 1.前言2. 通过curl -O 下载远端文件2.1 执行curl -O下载远端文件2.2 通过curl -v 查看详细的请求和响应的信息 3.通过在curl -O 中增加 -L 参数保证curl能够自动跟踪和请求远端返回的重定向地址4.结论 1.前言 最近在进行线上项目调试的过程中需要安装调试工具&#xf…

HubSpot能不能对接微信公众号?

在当今数字化时代&#xff0c;企业的数字化营销策略不可或缺。其中&#xff0c;HubSpot作为一体化营销平台&#xff0c;是否能与国内最大的社交平台之一——微信公众号进行无缝对接&#xff0c;成为业界关注的焦点。今天运营坛将深入探讨HubSpot与微信公众号的对接流程、Messag…

【华为 ICT HCIA eNSP 习题汇总】——题目集6

1、IEEE 802.11g 标准支持的最大协商速率为&#xff08;&#xff09;。 A、300Mbps B、150Mbps C、54Mbps D、1200Mbps 考点&#xff1a;无线局域网 解析&#xff1a;&#xff08;C&#xff09; IEEE 802.11系列标准如下表&#xff1a; 标准数据传输速率主要技术IEEE 802.111M…

【网站项目】医院管理系统源码(有源码)

🙊作者简介:多年一线开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板,帮助书写开题报告。作者完整代码目录供你选择: 《Springboot网站项目…

『OpenCV-Python鼠标画笔』

OpenCV-Python教程链接&#xff1a; https://opencv-python-tutorials.readthedocs.io/ 示例一&#xff1a;图片上双击的位置绘制一个圆圈 首先创建一个鼠标事件回调函数&#xff0c;鼠标事件发生时就会被执行。鼠标事件可以是鼠标上的任何动作&#xff0c;比如左键按下&#x…

论述Python中列表、元组、字典和集合的概念

Python列表是用于存储任意数目、任意类型的数据集合&#xff0c;包含多个元素的有序连续的内存空间&#xff0c;是内置可变序列&#xff0c;或者说可以任意修改。在Python中&#xff0c;列表以方括号&#xff08;[ ]&#xff09;形式编写。 Python元组与Python列表类似&#x…

蓝桥杯官网填空题(01串的熵)

问题描述 答案提交 这是一道结果填空的题, 你只需要算出结果后提交即可。本题的结果为一 个整数, 在提交答案时只填写这个整数, 填写多余的内容将无法得分。 import java.util.*;public class Main {public static void main(String[] args) {for(double zero1;zero<2333…

[docker] Docker资源管理

一、docker资源控制 Docker通过Cgroup 来控制容器使用的资源配额&#xff0c;包括CPU、内存、磁盘三大方面&#xff0c;基本覆盖了常见的资源配额和使用量控制。Caroup 是ControlGroups的缩写&#xff0c;是Linux 内核提供的一种可以限制、记录、隔离进程组所使用的物理资源(如…