groupby的字段必须是_诡异的OrderBy和GroupBy联合查询乱序问题

189a9c3dd09c9bb8c08e34ed0938dfe5.png

今日搬砖血泪史 

39aa541ef0f00683d517b31de2212142.png 792fccd628ea91732ec2804f9ef018d9.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的价格:

f65f0d43f54b8511d2f2ffdcead731b8.png

使用写好的sql执行,查到的结果如下:

cbe105e2386957804871e86dddb2f745.png

介尼玛就有点意思了,理想很丰满现实很骨感啊,于是将sql拆开查找问题出在哪,首先执行对价格确认时间的排序语句,结果如下:

913a2c98c3ec17f40af155056c72189e.png

排序结果和预想一毛一样,那为啥再对结果进行GroupBy取到的数据就不是想要的第一条了呢,此时靓仔语塞,脑子里抛出了成百上千万个为什么???

在这里再一次感谢度娘,没有度娘的话我这面子在公司往哪搁,谁还不是个体面人嘛。

接下来就是按照网上素未谋面的大佬的方法一阵骚操作,执行sql后看到结果的我就差眼泪流下来了...

a400ea864056bc4f7630630f53f64582.png

这骚操作其实就是在排序语句后增加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)。

1974742e0311ea661c0e9ee56efe06b6.png

因此Order by在子查询中如果不加Limit则会被优化掉而排序失效。

6ddd58c803817e489ef55ee7e17b1815.gif 792fccd628ea91732ec2804f9ef018d9.gif

d8604950ab9c7ce2d698dbb8d1f4956b.gif

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值