![189a9c3dd09c9bb8c08e34ed0938dfe5.png](https://i-blog.csdnimg.cn/blog_migrate/38b7d86b6f1faf9fde5b4151b5632aa1.png)
今日搬砖血泪史
![39aa541ef0f00683d517b31de2212142.png](https://i-blog.csdnimg.cn/blog_migrate/ee086baa12c096dda3e0fd86889757cd.png)
![792fccd628ea91732ec2804f9ef018d9.gif](https://i-blog.csdnimg.cn/blog_migrate/d454b07283e24f8a85493b31a5e9b1b8.gif)
手头有个需求,需要将商品调价后的最新价格通过定时任务更新到商品信息表中,商品价格表中每个门店内的每个商品都会存在多条调价记录,记录的确认时间是不同的,因此要拿到最新的调价后的价格需要根据调价确认时间进行排序,取最新的一条价格数据,于是就有了下面的sql语句:
SELECT t.storecode, t.shopid, t.price_new, t.time_confirmFROM (SELECT tln.storecode,
tln.shopid,
tln.price_new,
tln.time_confirmFROM t_xx_xxxprice tln where price_new != 0order by time_confirm desc) as tgroup by storecode, shopid;
接下来按计划疯狂撸代码、提交、发版、测试,看到测试结果的时候我一脸懵逼,原本以为会稳如一条老狗,结果啪啪打脸,于是开始查找问题原因,一遍遍执行sql对比数据,研究了半天一点眉目都没有,无奈打开度娘一阵查找,终究是皇天不负有心人,网上有大佬遇到过这种问题,后来根据大佬给的方案试了试,艾玛真香~
于是乎搞了点数据把过程记录下来分享下。
首先造三条同一商品调价记录,商品id为10000001,所属门店为9999,依据需求对生效时间confirm进行排序可以得到有效数据应为0.10的价格:
使用写好的sql执行,查到的结果如下:
介尼玛就有点意思了,理想很丰满现实很骨感啊,于是将sql拆开查找问题出在哪,首先执行对价格确认时间的排序语句,结果如下:
排序结果和预想一毛一样,那为啥再对结果进行GroupBy取到的数据就不是想要的第一条了呢,此时靓仔语塞,脑子里抛出了成百上千万个为什么???
在这里再一次感谢度娘,没有度娘的话我这面子在公司往哪搁,谁还不是个体面人嘛。
接下来就是按照网上素未谋面的大佬的方法一阵骚操作,执行sql后看到结果的我就差眼泪流下来了...
这骚操作其实就是在排序语句后增加limit字段,这操作简直amazing,但我还是依然懵逼状态,这才有了接下来的血泪总结:
原来,在MySQL 5.7版本上对子查询进行了优化,子查询的优化是使用半连接的策略完成的(The optimizer uses semi-join strategies to improve subquery execution)
使用半连接进行优化,子查询语句必须满足一些标准(In MySQL, a subquery must satisfy these criteria to be handledas a semi-join)。
其中一个标准是:必须不是一个包含了limit和order by的语句(It must not have ORDER BY with LIMIT)。
因此Order by在子查询中如果不加Limit则会被优化掉而排序失效。
![6ddd58c803817e489ef55ee7e17b1815.gif](https://i-blog.csdnimg.cn/blog_migrate/9830c13f1bc478caae3b923178602b19.gif)
![792fccd628ea91732ec2804f9ef018d9.gif](https://i-blog.csdnimg.cn/blog_migrate/d454b07283e24f8a85493b31a5e9b1b8.gif)