在Mysql中的GROUP BY分组,如何取最新的一条记录?

本文介绍三种SQL查询方法,用于从数据库中找出每个用户的最新借阅记录。包括直接使用聚合函数、子查询及group by结合join的方法,并分析了各自的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

导读日常开发当中,经常会遇到查询分组数据中最新的一条记录,比如统计当前系统每个人的最新登录记录、外卖系统统计所有买家最新的一次订单记录、图书管理系统借阅者最新借阅书籍的记录等等。

在Mysql中的GROUP BY分组,如何取最新的一条记录?在Mysql中的GROUP BY分组,如何取最新的一条记录?

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

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 

运行效果如下:

在Mysql中的GROUP BY分组,如何取最新的一条记录?在Mysql中的GROUP BY分组,如何取最新的一条记录?

参考资源链接:[MySQL GROUP BY 分组每组前N条记录的三种方法](https://wenku.youkuaiyun.com/doc/6453096cea0840391e76c7b3?utm_source=wenku_answer2doc_content) 在MySQL数据库中,通过GROUP BY语句可以实现对数据的分组统计,但当需要对每个分组前N条记录时,就需要运用一些高级的SQL技巧。首先,值得推荐的是查看资源《MySQL GROUP BY 分组每组前N条记录的三种方法》,它为你提供了多种解决方案,直接关联到你当前的问题,并能帮助你高效地解决分组记录的需求。 以下是使用JOIN、子查询、LIMIT等技术来实现这一需求的详细步骤: 1. 使用LEFT JOIN结合HAVING子句: 这种方法适用于需要对每个分组前N条记录的场景。通过LEFT JOIN连接同一表的副本来为每个记录找到同组中其他具有更高值的记录。然后通过HAVING子句来筛选出在每个分组中高于其值的记录数少于N的记录。 示例代码如下: ```sql SELECT t.* FROM your_table t LEFT JOIN your_table t2 ON t.grouping_column = t2.grouping_column AND t.value_column < t2.value_column GROUP BY t.id HAVING COUNT(t2.id) < N ORDER BY t.grouping_column, t.value_column DESC; ``` 2. 使用子查询(嵌套查询): 通过在WHERE子句中使用子查询,可以获每个分组内前N条记录。子查询会返回每个分组中排名在前N的记录的ID,然后主查询根据这些ID获完整记录。 示例代码如下: ```sql SELECT * FROM your_table WHERE id IN ( SELECT id FROM your_table GROUP BY grouping_column ORDER BY value_column DESC LIMIT N ) ORDER BY grouping_column, value_column DESC; ``` 3. 使用LIMIT子句结合子查询: 这种方法需要更加小心地构造子查询,确保能够正确地返回每个分组中前N条记录的ID或记录本身。需要注意的是,这种方法在某些情况下可能会导致错误,因此可能需要额外的逻辑来确保查询的准确性。 示例代码如下: ```sql SELECT * FROM your_table t WHERE (t.grouping_column, t.value_column) IN ( SELECT grouping_column, value_column FROM your_table GROUP BY grouping_column ORDER BY value_column DESC LIMIT N ) ORDER BY t.grouping_column, t.value_column DESC; ``` 在实际应用中,选择哪一种方法决于具体的数据规模和性能要求。在处理大规模数据时,确保为分组和排序字段建立适当的索引是非常重要的。此外,每种方法都有其适用场景和潜在的性能影响,建议根据实际情况进行选择和优化。 对于希望深入学习MySQL分组记录技术的读者,除了前面提到的《MySQL GROUP BY 分组每组前N条记录的三种方法》外,还可以查阅更多关于SQL查询优化和高级查询技术的资料,以便更好地理解和掌握这类复杂查询的实现。 参考资源链接:[MySQL GROUP BY 分组每组前N条记录的三种方法](https://wenku.youkuaiyun.com/doc/6453096cea0840391e76c7b3?utm_source=wenku_answer2doc_content)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值