mysql limit if,没有LIMIT的MySQL 5.7 RAND()和IF()会导致意外结果

I have the following query

SELECT t.res, IF(t.res=0, "zero", "more than zero")

FROM (

SELECT table.*, IF (RAND()<=0.2,1, IF (RAND()<=0.4,2, IF (RAND()<=0.6,3,0))) AS res

FROM table LIMIT 20) t

which returns something like this:

1a4ece5c36bda31452ecffe2424f7c6a.png

That's exactly what you would expect. However, as soon as I remove the LIMIT 20 I receive highly unexpected results (there are more rows returned than 20, I cut it off to make it easier to read):

SELECT t.res, IF(t.res=0, "zero", "more than zero")

FROM (

SELECT table.*, IF (RAND()<=0.2,1, IF (RAND()<=0.4,2, IF (RAND()<=0.6,3,0))) AS res

FROM table) t

b644f96be42e38e3f7525f699d0a4183.png

Side notes:

I'm using MySQL 5.7.18-15-log and this is a highly abstracted example (real query is much more difficult).

I'm trying to understand what is happening. I do not need answers that offer work arounds without any explanations why the original version is not working. Thank you.

Update:

Instead of using LIMIT, GROUP BY id also works in the first case.

Update 2:

As requested by zerkms, I added t.res = 0 and t.res + 1 to the second example

525f9a95e6cf78e524ac2e8eaecadd97.png

解决方案

The problem is caused by a change introduced in MySQL 5.7 on how derived tables in (sub)queries are treated.

Basically, in order to optimize performance, some subqueries are executed at different times and / or multiple times leading to unexpected results when your subquery returns non-deterministic results (like in my case with RAND()).

There are two easy (and likewise ugly) workarounds to get MySQL to "materialize" (aka return deterministic results) these subqueries: Use LIMIT or GROUP BY id both of which force MySQL to materialize the subquery and return the expected results.

The last option is turn off derived_merge in the optimizer_switch variable: derived_merge=off (make sure to leave all the other parameters as they are).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值