MySQL 分组后取每组前N条数据

与oracle的 rownumber() over(partition by xxx  order by xxx )语句类似,即:对表分组后排序

CREATE TABLE `mygoods` (  `goods_id` int(11) unsigned NOT NULL AUTO_INCREMENT,  `cat_id` int(11) NOT NULL DEFAULT '0',  `price` tinyint(3) NOT NULL DEFAULT '0',  `status` tinyint(3) DEFAULT '1',  PRIMARY KEY (`goods_id`),  KEY `icatid` (`cat_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;  INSERT INTO `mygoods` VALUES (1, 101, 90, 0);
INSERT INTO `mygoods` VALUES (2, 101, 99, 1);
INSERT INTO `mygoods` VALUES (3, 102, 98, 0);
INSERT INTO `mygoods` VALUES (4, 103, 96, 0);
INSERT INTO `mygoods` VALUES (5, 102, 95, 0);
INSERT INTO `mygoods` VALUES (6, 102, 94, 1);
INSERT INTO `mygoods` VALUES (7, 102, 93, 1);
INSERT INTO `mygoods` VALUES (8, 103, 99, 1);
INSERT INTO `mygoods` VALUES (9, 103, 98, 1);
INSERT INTO `mygoods` VALUES (10, 103, 97, 1);
INSERT INTO `mygoods` VALUES (11, 104, 96, 1);
INSERT INTO `mygoods` VALUES (12, 104, 95, 1);
INSERT INTO `mygoods` VALUES (13, 104, 94, 1);
INSERT INTO `mygoods` VALUES (15, 101, 92, 1);
INSERT INTO `mygoods` VALUES (16, 101, 93, 1);
INSERT INTO `mygoods` VALUES (17, 101, 94, 0);
INSERT INTO `mygoods` VALUES (18, 102, 99, 1);
INSERT INTO `mygoods` VALUES (19, 105, 85, 1);
INSERT INTO `mygoods` VALUES (20, 105, 89, 0);
INSERT INTO `mygoods` VALUES (21, 105, 99, 1);  

说明:

表mygoods为商品表,cat_id为分类id,goods_id为商品id,status为商品当前的状态位(1:有效,0:无效)。

需求:每个分类下,找出两个价格最高的有效的商品。

1.每个分类找出价格最高的两个商品

mysql> select a.*   -> from mygoods a   -> where (select count(*) -> from mygoods -> where cat_id = a.cat_id and price > a.price  ) <2 -> order by a.cat_id,a.price desc;

SQL解析:
cat_id = a.cat_id  --是为了确定分组字段
price > a.price  --确定排序条件,由于是大于,则最大出现0次,第二大的出现1次,所以count(*)<2

+----------+--------+-------+--------+
| goods_id | cat_id | price | status |
+----------+--------+-------+--------+
|        2 |    101 |    99 |      1 |
|       17 |    101 |    94 |      0 |
|       18 |    102 |    99 |      1 |
|        3 |    102 |    98 |      0 |
|        8 |    103 |    99 |      1 |
|        9 |    103 |    98 |      1 |
|       11 |    104 |    96 |      1 |
|       12 |    104 |    95 |      1 |
|       21 |    105 |    99 |      1 |
|       20 |    105 |    89 |      0 |
+----------+--------+-------+--------+
10 rows in set (0.00 sec)

2.每个分类找出价格最高的有效的两个商品(正确)

mysql> select a.* -> from mygoods a -> where (select count(*) from mygoods -> where cat_id = a.cat_id and price > a.price and status=1  ) <2 -> and status=1 -> order by a.cat_id,a.price desc ;

+----------+--------+-------+--------+
| goods_id | cat_id | price | status |
+----------+--------+-------+--------+
|        2 |    101 |    99 |      1 |
|       16 |    101 |    93 |      1 |
|       18 |    102 |    99 |      1 |
|        6 |    102 |    94 |      1 |
|        8 |    103 |    99 |      1 |
|        9 |    103 |    98 |      1 |
|       11 |    104 |    96 |      1 |
|       12 |    104 |    95 |      1 |
|       21 |    105 |    99 |      1 |
|       19 |    105 |    85 |      1 |
+----------+--------+-------+--------+
10 rows in set (0.00 sec)

3.每个分类找出价格最高的有效的两个商品(正确)

mysql> select a.* -> from mygoods a -> left join mygoods b -> on a.cat_id = b.cat_id and a.price < b.price and b.status=1-> where a.status=1-> group by a.goods_id,a.cat_id,a.price-> having count(b.goods_id) < 2-> order by a.cat_id,a.price desc;

+----------+--------+-------+--------+
| goods_id | cat_id | price | status |
+----------+--------+-------+--------+
|        2 |    101 |    99 |      1 |
|       16 |    101 |    93 |      1 |
|       18 |    102 |    99 |      1 |
|        6 |    102 |    94 |      1 |
|        8 |    103 |    99 |      1 |
|        9 |    103 |    98 |      1 |
|       11 |    104 |    96 |      1 |
|       12 |    104 |    95 |      1 |
|       21 |    105 |    99 |      1 |
|       19 |    105 |    85 |      1 |
+----------+--------+-------+--------+
10 rows in set (0.00 sec)

4.每个分类找出价格最高的有效的两个商品(错误)

mysql> select a.* -> from mygoods a -> where (select count(*) from mygoods -> where cat_id = a.cat_id and price > a.price  ) <2 and status=1 -> order by a.cat_id,a.price desc;

+----------+--------+-------+--------+
| goods_id | cat_id | price | status |
+----------+--------+-------+--------+
|        2 |    101 |    99 |      1 |
|       18 |    102 |    99 |      1 |
|        8 |    103 |    99 |      1 |
|        9 |    103 |    98 |      1 |
|       11 |    104 |    96 |      1 |
|       12 |    104 |    95 |      1 |
|       21 |    105 |    99 |      1 |
+----------+--------+-------+--------+
7 rows in set (0.00 sec)

由上可知,如果需要增加条件的话,需要在两处增加条件。

可以将每个分组下的goods_id合并。

mysql> select cat_id,GROUP_CONCAT(goods_id) from mygoods group by cat_id;

+--------+------------------------+
| cat_id | GROUP_CONCAT(goods_id) |
+--------+------------------------+
|    101 | 1,2,15,16,17           |
|    102 | 3,5,6,7,18             |
|    103 | 4,8,9,10               |
|    104 | 11,12,13               |
|    105 | 19,20,21               |
+--------+------------------------+
5 rows in set (0.00 sec)

https://blog.csdn.net/come_on_air/article/details/72902592

MySQL取每组的前N条记录:使用自连接的方式

一、对分组的记录取前N条记录:例子:取前 2条最大(小)的记录

1.用子查询: SELECT*
FROMright2 a
WHERE2 > (SELECTCOUNT(*)FROMright2 bWHEREb.id = a.idAND b.account > a.account)
ORDER BYa.id,a.account DESC 2.用exists半连接: SELECT*FROMright2 aWHEREEXISTS (SELECTCOUNT(*)FROMright2 bWHEREb.id = a.idAND a.account < b.accountHAVINGCOUNT(*) < 2)ORDER BYa.id,a.account DESC 同理可以取组内最小的N条记录: SELECT*FROMright2 aWHERE2 > (SELECTCOUNT(*)FROMright2 bWHEREb.id = a.idAND b.account < a.account)ORDER BYa.id,a.account DESC 用exists: SELECT*FROMright2 aWHEREEXISTS (SELECTCOUNT(*)FROMright2 bWHEREb.id = a.idAND a.account > b.accountHAVINGCOUNT(*) < 2)ORDER BYa.id,a.account DESC SQLServer支持top - N: SELECTa.*FROMtb aWHEREval = (SELECTtop 3 valFROMtbWHERENAME = a. NAME)ORDER BYa. NAME

如果取每组的最大(小)一条记录我常用:

SELECTid,val
FROMt b
INNER JOIN (SELECT*FROMt aWHEREORDER BYval DESC
) a ON a.id = b.id
GROUP BYa.id
ORDER BYid;

二.实例:取每组最大的前 N条

CREATE TABLE t2 (id INT PRIMARY KEY,gid CHAR,col1 INT,col2 INT
) ENGINE = INNODB;INSERT INTO t2
VALUES(1, 'A', 31, 6),(2, 'B', 25, 83),(3, 'C', 76, 21),(4, 'D', 63, 56),(5, 'E', 3, 17),(6, 'A', 29, 97),(7, 'B', 88, 63),(8, 'C', 16, 22),(9, 'D', 25, 43),(10, 'E', 45, 28),(11, 'A', 2, 78),(12, 'B', 30, 79),(13, 'C', 96, 73),(14, 'D', 37, 40),(15, 'E', 14, 86),(16, 'A', 32, 67),(17, 'B', 84, 38),(18, 'C', 27, 9),(19, 'D', 31, 21),(20, 'E', 80, 63),(21, 'A', 89, 9),(22, 'B', 15, 22),(23, 'C', 46, 84),(24, 'D', 54, 79),(25, 'E', 85, 64),(26, 'A', 87, 13),(27, 'B', 40, 45),(28, 'C', 34, 90),(29, 'D', 63, 8),(30, 'E', 66, 40),(31, 'A', 83, 49),(32, 'B', 4, 90),(33, 'C', 81, 7),(34, 'D', 11, 12),(35, 'E', 85, 10),(36, 'A', 39, 75),(37, 'B', 22, 39),(38, 'C', 76, 67),(39, 'D', 20, 11),(40, 'E', 81, 36);

取每组gid 最大的前N条记录:使用自连接或则半连接:

*N=1时:

自连接:降序排好后group by取每组最大的一条。

SELECT*
FROM(SELECT*FROMt2ORDER BYcol2 DESC) AS a
GROUP BYgid
ORDER BYgid;

半连接方式:找不到比最大值还大的。

SELECT*
FROMt2 a
WHERENOT EXISTS (SELECT1FROMt2 bWHEREb.gid = a.gidAND b.col2 > a.col2)
ORDER BYa.gid;

*N=3时:

自连接:

SELECT*
FROMt2 a
WHERE3 > (SELECTcount(*)FROMt2WHEREgid = a.gidAND col2 > a.col2)
ORDER BYa.gid,a.col2 DESC;

半连接:

SELECT*
FROMt2 a
WHEREEXISTS (SELECTcount(*)FROMt2 bWHEREb.gid = a.gidAND a.col2 < b.col2HAVING(count(*)) < 3)
ORDER BYa.gid,a.col2 DESC

Oracle取每组的前N条记录:可以使用分析函数,hive中也能使用

SELECT * FROM(
SELECT z.type , z.code ,ROW_NUMBER()
OVER(PARTITION BY z.type ORDER BY z.code desc) AS code_id
FROM group_info z
)
WHERE code_id <4;   #取每组最大的前四条记录

https://blog.csdn.net/kuodannie1668/article/details/79756964

转载于:https://www.cnblogs.com/softidea/p/10268811.html

MySQL取每组的前N条记录相关推荐

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

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

  2. 【Mysql】Sql分组查询后取每组的前N条记录

    目录 一.背景 二.实战解析 三.总结 一.背景 最近,在开发中遇到个功能需求.系统有个资讯查询模块,要求资讯按照卡片形式展示.如下图: 按照项目组展示卡片,每个项目组展示阅读量最多的TOP2. 需求 ...

  3. mysql随机取出每个分组前2条记录

    mysql随机取出每个分组前2条记录 SELECT a.* FROMt_notary_business AS a,(SELECT GROUP_CONCAT(id order by rand()) AS ...

  4. mysql 排序取前4,mysql分组取每组前几条记录(排序)

    首先来造一部分数据,表mygoods为商品表,cat_id为分类id,goods_id为商品id,status为商品当前的状态位(1:有效,0:无效). CREATE TABLE `mygoods` ...

  5. mysql提取前两个数据_各种数据库提取表的前几条记录的方法

    前一阵子去了个面试,其中有个道考题是写出取某张表前10条记录的sql语句.一头雾水,回来问了同学也没有结果,近来上网搜了一下,收获如下: 原来不同的DBMS对此操作的sql语句也不同. (取出TABL ...

  6. mysql分组查询选择数量最多的前十个_mysql 查询每一个分组前N条记录

    mysql 查询每一个分组前N条记录html 假设存在表movie,  有字段 id, part(地区), mcount(观看次数)mysql 现查询每一个地区观看次数最多的3部movie, 则表sq ...

  7. mysql单列去重复group by分组取每组前几条记录加order by排序

    <div class="post"><h1 class="postTitle"><a id="cb_post_title ...

  8. php sql跳过前四条数据,mysql实现每组取前N条记录的sql,以及后续的组数据量限制...

    select a.msg_id, a.com_id, a.data, a.ctime from sns_user_03.user_request_86 a where 5 (select count( ...

  9. mysql实现每组取前N条记录的sql,以及后续的组数据量限制

    应用场景大概是这样的:比如有很多消息流,这些消息来自不通的app,聚合在一个页面上,查看的时候不能让一个app的消息霸屏,所以就会类似于折叠功能,同一个app的消息只显示最多5条,再多的话,就要点进去 ...

  10. mysql 分组排序取前n_mysql分组排序取前N条记录的最简洁的单条sql ! | 学步园

    -- mysql分组排序取前N条记录的最简洁的单条sql. use test; drop table if exists test; create table test ( id int primar ...

最新文章

  1. go网站服务器搭建,使用Go搭建服务器记录(一)
  2. 为什么大公司一定要使用微服务?
  3. Running Maven project on Tomcat from Eclipse
  4. 在VS2005的工具箱中增加SharePoint的活动
  5. 计算多项式的值(信息学奥赛一本通-T1012)
  6. pcie usb3.0 驱动 for linux_微软WSL——Linux桌面版未来之光
  7. C# 使用SFTP的上传下载文件时如何使用代理
  8. GCC源码自动编译-python脚本
  9. 【springboot】启动流程之starting
  10. 上传图片到淘宝接口调用展示
  11. 关于如何调用苹果自带的地图APP
  12. 【解题报告】openjudge Freda的越野跑 数据结构与算法mooc 内排序
  13. 资产配置记录20210814
  14. clover写入efi_把clover复制到EFI之后电脑不认clover的解决方法(UEFI Shell强制写入)
  15. java ssh免密登录_SSH免密登录(单信)
  16. Python:SM4
  17. 关于论文格式要求及字体大小
  18. 2020第十一届蓝桥杯国赛JAVA B组真题解析(带源码及解析)
  19. 【软件工程】 文档 - 银行业务管理 - 结构化设计
  20. 时间差之天数计算Python

热门文章

  1. Atitit Major island groups and archipelagos 主要的岛群和群岛目录资料目录1. 岛群 波利尼西亚(Polynesia, 美拉尼西亚(Melanesia,
  2. Atitit.vs2017 visual studio vs2003 vs2005 vs2008 VS2010 vs2012 vs2015新特性 新功能.docx Atitit. visual st
  3. Atitit 知识点 文章 框架 结构 attilax总结.docx
  4. paip.android 手机输入法制造大法
  5. 网页图片显示分辨率与实际分辨率不一样
  6. .Net 机器学习资源,你有想要的么
  7. Kafka从上手到实践 - Kafka CLI:Topic CLI Producer CLI | 凌云时刻
  8. 【图像去噪】基于matlab GUI均值+中值图像去噪【含Matlab源码 1815期】
  9. 【电路仿真】基于matlab BP神经网络三相逆变器故障诊断【含Matlab源码 1655期】
  10. 【多目标优化求解】基于matlab自适应风驱动算法求解多目标优化问题【含Matlab源码 1414期】