作者:Whiterock_Lelik

blog.csdn.net/lglaljj123/article/details/79864188

最近在工作中遇到一个先排序后分组的需求,发现MySql不同的版本有不同的结果,特此记录。

举例:要求在shop表中查询出各类型商店中价格最高的商品。

--表结构--
create table `shop` (`id` int (10) PRIMARY KEY,`shop_name` varchar (100),`item_name` varchar (100),`price` int (10)
); insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('1','小卖部','酱油','12');
insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('2','小卖部','醋','15');
insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('3','小卖部','脉动','20');
insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('4','小卖部','沙姜','2');
insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('5','超市','猪肉','24');
insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('6','超市','生菜','6');
insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('7','超市','菜心','5');
insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('8','连锁店','生姜','3');
insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('9','超市','牛肉','30');
insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('10','连锁店','蒜头','2');
insert into `shop` (`id`, `shop_name`, `item_name`,`price`) values('11','连锁店','黄瓜','20');

那么很自然地就想到了对价格price进行排序然后再根据商店类型shop_name进行分组查询

select * from (select * from shop order by price desc) a GROUP BY a.shop_name

这条sql很简单易懂,接下来我们验证一下是否正确:

期望结果:

MySql 5.7.20下的实际结果:

可以看出来实际上得出的结果只是按照表数据的顺序,简单地进行了分组查询操作,但是这时候我们还不能下结论说这条sql就是错误的,我们用另一个数据库版本(MySql 5.5.57)测试一下。

MySql 5.5.57下的结果:

为什么会有不同的结果?

我们分别查看一下这条sql在两个不同版本数据库的执行计划:

MySql 5.7.20:

MySql 5.5.57:

对比可以发现5.7版本的MySql在执行这条sql时缺少了一个derived操作,通过查阅相关资料了解到MySql 5.7对子查询进行了优化,认为子查询中的order by可以进行忽略,只要Derived table里不包含如下条件就可以进行优化:

  1. UNION clause

  2. GROUP BY

  3. DISTINCT

  4. Aggregation

  5. LIMIT or OFFSET


最后放上相应的解决办法:

--方法一,仅适用于低于5.7版本的MySql--
select * from (select * from shop order by price desc) a GROUP BY a.shop_name; --方法二--
select * from (select * from shop order by price desc limit 999999) a GROUP BY a.shop_name;--方法三--
select * from shop a where N > (select count(*) from shop b where b.shop_name = a.shop_name and a.price < b.price) order by a.shop_name,a.price desc;

方法二中使用limit,需要limit的范围足够大能包括所有数据,并且每种分类只会显示一条数据,但是数据较多时运行效率要比方法三快上很多,方法三能够控制每种分类显示多少条数据,把N换成需要显示对应的数字即可。

END

推荐好文

强大,10k+点赞的 SpringBoot 后台管理系统竟然出了详细教程!分享一套基于SpringBoot和Vue的企业级中后台开源项目,代码很规范!
能挣钱的,开源 SpringBoot 商城系统,功能超全,超漂亮!

MySQL下实现先排序后分组查询(问题记录)相关推荐

  1. oracle不排序分页结果随机,关于ORACLE排序后分页查询出现反复数据的探讨

    关于ORACLE排序后分页查询出现重复数据的探讨 最近在帮一个同事调试BUG,有一个条BUG是这样描述的: 所有有排序功能的列表,当其中某一字段当前页面内容一致时,翻页就有误. 页码改变,列表内容不变 ...

  2. MySQL 查询优化(八):分组查询该怎么优化?

    MySQL 在处理 GROUP BY 和 DISTINCT 查询的方式在大多数情况下类似,事实上,在优化过程中有时候会把在这两种方式中转换.两类查询都能够从索引中受益,通常,这也是优化这两种查询最为重 ...

  3. laravel 先排序后分组怎么写_插入排序的故事

    话说计算机世界有一个诚实国,那里的人们不但诚实,而且尊老,每次排队都让年纪大的人排前面. 有一次小胖到诚实国去旅游,肚子饿了想吃东西,发现一个烧饼店门前有人排着队,他就跟在队伍后面一起排队.没过多久, ...

  4. laravel 先排序后分组怎么写_希尔排序算法拆解解析

    1先让我们回顾下插入排序 //比如有组数据:int[] arr = {8, 6, 2, 3, 1, 5, 7, 4}; 文字概述: 假设第一个元素为最小数字.那么我们就要从index=1开始往后循环, ...

  5. mysql分组失效_请教MySql中使用表子查询时,试着先排序后分组,出现排序失效的原因?...

    1,今天试着码了一下教程里的题目,是找出每一个班级的身高最高的学生,用的是先order by降序排序所有学生升高,再用 group by分组每一个班级取第一个值,却发现当使用子查询时,得到的仍旧是未排 ...

  6. mysql 排序后在查询

    今天写sql 的时候,遇到一个问题,有一个图书表和一个章节表 book{ id,name,cover}   chapter{id,bid,rank,content,title} 我需要随机五本书,并且 ...

  7. mysql筛选班级排名_mysql实现分组查询每个班级的前三名

    1.创建表 drop table student; create table student( id varchar(20),-- 编号 class varchar(20),-- 年级 score i ...

  8. [NHibernate]获取分组查询的记录总数

    项目使用NHibernate2.1.0.今天遇到一个很闹心的问题,我们有一个带分组的分页查询 var q = Session.CreateQuery(@"select t.PMM,t.Ret ...

  9. oracle排序后的第一条记录

    该查寻语句没有经过任何的优化,因为oracle没有SQL的TOP关键字,但是有一个ROWNUM的列,因此,可以通过ROWNUM来进行查询.oracle的关于rownum的参考手册里面提到了    分析 ...

最新文章

  1. 10000+ gif表情包不是梦,get这一篇文就够了!!!小哥哥快到碗里来,再也不怕斗图没有表情包了
  2. 小程序获取用户的操作轨迹日志
  3. 搞懂Kafka的这个问题,你离大厂就不远了!
  4. 产品成功之后的品牌策略
  5. python android自动化元素定位_linux下Appium+Python移动应用自动化测试实战---3.手把手教你定位元素编写测试用例...
  6. leetcode 398. Random Pick Index | 398. 随机数索引(Java)
  7. git 放弃本地修改,强制拉取更新
  8. C#实现文件与二进制互转并存入数据库
  9. Linux学习总结(66)——CentOS7操作系统SSH安全加固
  10. 深入了解什么是服务网格
  11. redis hash field过期时间_大佬来告诉你用事半功倍的办法,学习Redis,你觉得它还难吗?...
  12. Hiho----无间道之并查集
  13. Win8下Qualcomm Atheros AR9285网卡改mac
  14. android 屏幕点击录制视频教程,安卓手机怎么屏幕录像,手机屏幕录像详细教程...
  15. 挑战杯创业计划书_基于云计算的下料优化软件_1. 执行总结
  16. android组合键截图原理,步步高vivo x7怎么截屏 组合键截图方法教程
  17. 51系列单片机寻址方式
  18. 利用反向代理服务器,加快国内对国外主机的访问
  19. java抢红包_Java实现抢红包功能
  20. 安装Visio失败提示安装即点即用版本 利用office部署工具安装visio2016

热门文章

  1. 阿里巴巴公布“新六脉神剑”:因为信任 所以简单
  2. 腾讯员工平均月薪7万?腾讯回应:完全不能这么算
  3. 安装这些App的注意了!隐私窃取 捆绑推广 已被下架 现在卸载还来得及!
  4. iis5.1安装方法(适用于XP)以及运行调试asp程序,创建虚拟目录【整理】
  5. 分析rss/xml结构附带源码【原创】
  6. 还不懂!软件测试(功能、接口、性能、自动化)详解
  7. android 动态地改变某控件的大小
  8. java中的页面:JSP(已过时)
  9. 用电饭锅做蛋糕的做法
  10. mysql复杂条件判断_MySQL复杂where条件分析