SQL分组查询后取每组的前N条记录

本文介绍了如何在SQL中实现按分类分组查询,并取每组的前N条记录。通过模拟数据和三种不同的SQL实现方法,详细解释了如何在MySQL中利用子查询和聚合函数解决此类问题,强调了解决问题的思维方式的重要性。

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

 
 
 
 


640?wx_fmt=jpeg

本文由 Leon 同学授权发布

这个公众号的关注者除了大部分是 Android 工程师之外还有部分后端以及前端同学,我鼓励也非常欢迎大家来投稿,其实我们并不需要把自己限定在某个领域,多学学其他语言也是非常不错的,欢迎投稿!~

另外大家不要觉得自己写不好,不用怕,我可以指导你,Leon 同学在我指导下就改了几版,进步非常大,写文章既能让自己加深印象又能帮助别人,何乐不为呢?

一、前言

分组查询是常见的SQL查询语句。首先,我们知道MySQL数据库分组功能主要是通过GROUP BY关键字来实现的,而且GROUP BY通常得配合聚合函数来使用用,比如说分组之后你可以计数(COUNT),求和(SUM),求平均数(AVG)等。但是今天我们要探讨的不是GROUP BY关键字学习和使用,而是一种有点另类的“分组”查询。

最近,项目上遇到这样一个功能需求。系统中存在资讯信息这样一个功能模块,用于发布一些和业务相关的活动动态,其中每条资讯信息都有一个所属类型(如科技类的资讯、娱乐类、军事类···)和浏览量字段。


而业务系统的官网上需要滚动展示一些热门资讯信息列表(浏览量越大代表越热门),而且每个类别的相关资讯记录至多显示3条,换句话:“按照资讯分类分组,取每组的前3条资讯信息列表”。

后面在尝试 GROUP BY 使用的各种方式都不能实现,最后在查阅相关资料后找到了实现的解决方法。

下面,我将模拟一些实际的测试数据重现问题的解决过程。

一、数据准备

数据库: MySQL 8.0社区版

表设计

id 主键
name 分类名称
code 说明
id 主键
title 资讯名称
views 浏览量
info_type_id 资讯类别

初始化SQL语句:

 1DROP TABLE IF EXISTS `info`; 2CREATE TABLE `info`  ( 3  `id` int(11) NOT NULL AUTO_INCREMENT, 4  `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, 5  `views` int(255) DEFAULT NULL, 6  `info_type_id` int(11) DEFAULT NULL, 7  PRIMARY KEY (`id`) USING BTREE 8) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; 910-- ----------------------------11-- Records of info12-- ----------------------------13INSERT INTO `info` VALUES (1, '中日海军演习', 10, 4);14INSERT INTO `info` VALUES (2, '美俄军事竞赛', 22, 4);15INSERT INTO `info` VALUES (3, '流浪地球电影大火', 188, 1);16INSERT INTO `info` VALUES (4, '葛优瘫', 99, 2);17INSERT INTO `info` VALUES (5, '周杰伦出轨了', 877, 2);18INSERT INTO `info` VALUES (6, '蔡依林西安演唱会', 86, 1);19INSERT INTO `info` VALUES (7, '中纪委调盐', 67, 3);20INSERT INTO `info` VALUES (8, '人民大会堂', 109, 3);21INSERT INTO `info` VALUES (9, '重庆称为网红城市', 202, 1);22INSERT INTO `info` VALUES (10, '胡歌结婚了', 300, 2);23INSERT INTO `info` VALUES (11, 'ipone15马上上市', 678, 2);24INSERT INTO `info` VALUES (12, '中国探月成功', 54, 4);25INSERT INTO `info` VALUES (13, '钓鱼岛对峙', 67, 4);2627DROP TABLE IF EXISTS `info_type`;28CREATE TABLE `info_type`  (29  `id` int(11) NOT NULL AUTO_INCREMENT,30  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,31  PRIMARY KEY (`id`) USING BTREE32) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;3334-- ----------------------------35-- Records of info_type36-- ----------------------------37INSERT INTO `info_type` VALUES (1, '娱乐');38INSERT INTO `info_type` VALUES (2, '八卦');39INSERT INTO `info_type` VALUES (3, '政治');40INSERT INTO `info_type` VALUES (4, '军事');DROP TABLE IF EXISTS `info`;
2CREATE TABLE `info`  (
3  `id` int(11NOT NULL AUTO_INCREMENT,
4  `title` varchar(255CHARACTER
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值