MYSQL学习:GROUP BY分组取最新的一条记录

               

日常开发当中,经常会遇到查询分组数据中最新的一条记录,比如统计当前系统每个人的最新登录记录、外卖系统统计所有买家最新的一次订单记录、图书管理系统借阅者最新借阅书籍的记录等等。今天给大家介绍一下如何实现以上场景的SQL写法,希望对大家能有所帮助!

1、初始化数据表

-- 借阅者表
CREATE TABLE `userinfo` (`uid` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`uname` varchar(20) NOT NULL COMMENT '姓名',`uage` int(11) NOT NULL COMMENT '年龄',PRIMARY KEY (`uid`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
INSERT INTO `userinfo` VALUES (1, '小明', 20);
INSERT INTO `userinfo` VALUES (2, '小张', 30);
INSERT INTO `userinfo` VALUES (3, '小李', 28);
-- 书籍表
CREATE TABLE `bookinfo` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`book_no` varchar(20) NOT NULL COMMENT '书籍编号',`book_name` varchar(20) NOT NULL COMMENT '书籍名称',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
INSERT INTO `bookinfo` VALUES (1, 'ISBN001', '计算机基础');
INSERT INTO `bookinfo` VALUES (2, 'ISBN002', '计算机网络');
INSERT INTO `bookinfo` VALUES (3, 'ISBN003', '高等数学');
INSERT INTO `bookinfo` VALUES (4, 'ISBN004', '明朝那些事');
INSERT INTO `bookinfo` VALUES (5, 'ISBN005', '物理');
INSERT INTO `bookinfo` VALUES (13, 'ISBN006', '读者');
-- 借阅记录表
CREATE TABLE `borrow_record` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`user_id` int(11) NOT NULL COMMENT '用户id',`book_id` int(11) NOT NULL COMMENT '书籍id',`borrowtime` datetime NOT NULL COMMENT '书籍id',PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
INSERT INTO `borrow_record` VALUES (8, 1, 2, '2021-05-01 10:52:00');
INSERT INTO `borrow_record` VALUES (9, 2, 4, '2021-07-12 23:32:00');
INSERT INTO `borrow_record` VALUES (10, 2, 1, '2021-03-21 09:00:00');
INSERT INTO `borrow_record` VALUES (11, 1, 3, '2021-08-11 17:39:00');
INSERT INTO `borrow_record` VALUES (12, 1, 5, '2021-09-02 18:12:00');
INSERT INTO `borrow_record` VALUES (13, 3, 1, '2021-07-06 12:32:00');
INSERT INTO `borrow_record` VALUES (14, 2, 1, '2021-08-09 10:10:00');
INSERT INTO `borrow_record` VALUES (15, 4, 3, '2021-04-15 19:45:00'
);

写法1 直接group by 根据userid ,使用聚合函数max取得最近的浏览时间

select a.user_id ,max(c.uname) uname
,max(a.borrowtime) borrowtime,max(b.book_name) book_name
from borrow_record a 
INNER JOIN bookinfo b on b.id=a.book_id
INNER JOIN userinfo c on c.uid=a.user_id
GROUP BY a.user_id
-- 说明: 这样会存在获取书籍名称错乱的情况,
-- 因为使用聚合函数获取的书籍名称,不一定是对应用户
-- 最新浏览记录对应的书籍名称

写法2 采用子查询的方式,获取借阅记录表最近的浏览时间作为查询条件

select a.user_id ,c.uname,a.borrowtime 
,b.book_name book_namefrom borrow_record a 
INNER JOIN bookinfo b on b.id=a.book_id
INNER JOIN userinfo c on c.uid=a.user_id
where a.borrowtime=(select max(borrowtime) 
from borrow_record t where t.user_id=a.user_id)
-- 说明:可以满足查询效果,不过性能不是最优解

写法3 采用group by + join 性能最高,推荐采用

select a.user_id ,c.uname,a.borrowtime 
,b.book_name book_namefrom (
select t.user_id,max(borrowtime)  borrowtime
from borrow_record t GROUP BY t.user_id) as e INNER JOIN  borrow_record a on e.user_id=a.user_id 
and e.borrowtime=a.borrowtimeINNER 
JOIN bookinfo b on b.id=a.book_id
INNER JOIN userinfo c on c.uid=a.user_id

运行效果如下:

               

IT技术分享社区

个人博客网站:https://programmerblog.xyz

文章推荐程序员效率:画流程图常用的工具程序员效率:整理常用的在线笔记软件远程办公:常用的远程协助软件,你都知道吗?51单片机程序下载、ISP及串口基础知识硬件:断路器、接触器、继电器基础知识

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

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

相关文章

@SentinelResource注解实现热点限流

下图中请求url中param参数为axb,如果QPS超过5,就会限流 一:如下代码 RestController public class ParamController {GetMapping("/param")SentinelResource(value "param", blockHandler "exHandler")p…

硬件知识:固态硬盘4K对齐知识介绍

目录 1、什么是4K对齐呢? 2、怎么查看硬盘是否4K对齐呢? 3、怎么4K对齐呢? 现在大家基本都有一个固态硬盘,而在固态硬盘分区中4K对齐是非常重要的。 1、什么是4K对齐呢? “4K对齐”就是符合“4K扇区”定义格式化过的硬…

【spring cloud】注解@SpringCloudApplication和@SpringBootApplication的区别

SpringCloudApplication注解 注解SpringCloudApplication包括:SpringBootApplication、EnableDiscoveryClient、EnableCircuitBreaker,分别是SpringBoot注解、注册服务中心Eureka注解、断路器注解。对于SpringCloud来说,这是每一微服务必须应…

网络知识:路由器常见故障分析及处理方法

目录 1.路由器的部分功能无法实现 2.网络频繁掉线 3.无法浏览网页 4.某些应用无法使用 5.网络带宽达不到合同带宽或相差甚远 6.局域网内存在多个路由器,因人为原因出现二级路由 对当前的大多数网络来说,无论是实现网络互连还是访问Internet&a…

硬件技巧:如何隐设置的你的电脑U盘不可见

有时候电脑里面有重要内容,在不联网的情况下,还需要禁用U盘,下面介绍禁用U盘的方法,原创文章,转载注明出处即可。 第一步,首先在电脑上点击开始按钮,或者直接按下快捷键组合"WinR"&am…

前端知识:如何创建自己的Iconfont图标库

在日常的开发过程中,前端页面经常会引用一些图标,iconfont图标库是前端开发者非常友好的在线字体图标库。大家可以根据平常所涉及的项目,收藏自己需要的图标库,方便在后续的项目中使用,今天小编给大家介绍如何通过icon…

硬件:固态硬盘SSD的基础知识及安装注意事项

固态硬盘就是用固态电子存储芯片阵列而制成的硬盘,相对于机械硬盘,固态硬盘的读写速度更快,但是固态硬盘的缺点是寿命不如机械硬盘。 固态硬盘有写入寿命,平均起来约为3000次P/E,1P/E为硬盘存储上限,相当于…

C# Redis实战(二)

二、Redis服务 在C# Redis实战(一)中我将所有文件拷贝到了D盘redis文件夹下,其中redis-server.exe即为其服务端程序,双击即开始运行,如图可以将此服务设置为windows系统服务,下载Redis服务安装软件,安装即可。安装完成…

matlab仿真超声波测距,超声波测距仪制作-Arduino中文社区 - Powered by Discuz!

本帖最后由 xiebb5688 于 2017-12-4 09:06 编辑虽然学的是机械,可也接触过C语言,MATLAB等程序,每次编程的时候,能够把BUG一个个解决掉,会带来不小的成就感。于是感觉到自己骨子还是挺喜欢代码的。于是也不知何时了解了…

电脑技巧:键盘上的这几个键,不常用,但有必要了解一下

目录 键盘上三个特殊的键 Print Screen(或 Prt Scn) Scroll Lock(或 Scr Lk) Pause/Break ​​​​​​​ 键盘上三个特殊的键 通过前几期的文章,我们已经讨论了几乎所有可能要用到的键。但为了真正彻底地了解键盘&…

ip访问php $_files空,PHP中表单没有问题但$_FILES为空怎么办?

PHP中表单没有问题,但“$_FILES”为空的解决方法:首先在form中加代码为“enctype"multipart/form-data”;然后开启“file_uploads”并设置“file_uploadson”即可。PHP中表单没有问题但是$_FILES为空的解决办法在文件上传中$_FILES接收不…

一张图看透微信公众号、企业号、小程序

对于微信小程序,推荐了解关键词:“progress web app” 我觉得微信小程序跟原生app之间也没有什么好争议的,就如微信和手机qq一样,有了微信,手机QQ也没有死掉,微信小程序适合小型应用,或者说能用…

电脑技巧:电脑识别不出字,一些汉字都变成框框了

目录 一、区域语言设定 二、系统内部编码 三、字体库被破坏 四、Office工具修复 五、美化主题的问题 六、中毒,杀毒。 电脑识别不出字,一些汉字都变成框框了,该怎么办? 一、区域语言设定 控制面板——区域和语言选项——选项和高级…

const没define好用 php,3分钟短文|PHP 定义常量,我该用define还是const?这下不迷茫了...

引言我们今天说一下 PHP 编程中,定义一个常量所使用的两种方法。有哪些区别,以及哪种是最佳实践?问题有开发者说,我在学习编写 PHP,可是定义常量的方法很是让人迷惑。比如有下面这样的写法:define(FOO, 1);…

springboot+mybatis集成自定义缓存ehcache用法笔记

今天小编给大家整理了springbootmybatis集成自定义缓存ehcache用法笔记,希望对大家能有所办帮助!一、ehcache介绍EhCache 是一个纯Java的进程内缓存管理框架,属于开源的Java分布式缓存框架,主要用于通用缓存,Java EE和轻量级容器。…

Java取绝对值

在Java中可以使用Math.abs()方法来方便的进行绝对值计算,例如: 输入的是正数的时候直接返回即可,当是负数的时候返回它的相反数即可。 使用三目运算符可以使用一行代码就能做到 int value Math.abs(-90);System.out.println(value);System…

PHP怎么做一个加法口诀,神奇的手指速算口诀,100以内的加减法一分钟学会

手指速算是一套手、心、脑并用的科学计算方法,教孩子学会,既能开发大脑、增强动作协调能力和记忆力,还能增强学习兴趣哦~学起来并不难哦,爸爸妈妈可以和孩子一起算一算,比比看谁更快!手指速算秘诀准备&…

Android_Layout (一)

layout (布局) --->Android 有五大布局,分别是: LinearLayout : 线性布局,子组件按照垂直或者水平方向来布局。RelativeLayout :相对布局,按照控件之间的相互位置进行参照物的概念排布&…