《高性能MySQL》中ORDER BY ..., LEAST(0, @rownum := @rownum+1)的工作原理是什么?
嘿,这个问题挺有意思的,我来拆解一下这段SQL里ORDER BY ..., LEAST(0, @rownum := @rownum+1)的工作逻辑,结合你给出的结果一步步分析:
1. 先理清变量初始化的基础
首先SET @rownum := 0;就是把用户变量@rownum初始化成0,这个没什么复杂的,就是给变量一个起始值。
2. 核心:拆解ORDER BY里的表达式
这个表达式里藏着两个关键点:
@rownum := @rownum + 1:这是个变量自增的赋值操作,执行后@rownum会加1,而且这个表达式本身的返回值就是自增后的数值。LEAST(0, 上面的赋值结果):LEAST函数会返回传入参数里的最小值,不管@rownum自增后是1还是2,和0比最小值都是0。那加这个函数的意义在哪?重点根本不在LEAST的结果,而在于赋值操作会被强制执行——哪怕LEAST的结果不影响排序,MySQL在计算ORDER BY的表达式时,还是会老老实实执行@rownum的自增。
3. 结合你的结果看完整执行流程
你的结果里NICK的rownum是2,PENELOPE是1,这正好能说明执行顺序的细节:
- 初始
@rownum = 0,MySQL开始扫描sakila.actor表的行,首先要处理WHERE @rownum <= 1的条件,但这里的变量变化是和ORDER BY绑定的—— - MySQL会先对所有行执行
ORDER BY排序:- 排序的第一关键字是
first_name,所以最终结果会按字母顺序排列(NICK在PENELOPE前面,因为N比P的字母顺序更早)。 - 在排序过程中,MySQL会逐行计算
ORDER BY的第二个表达式:- 先处理原表中
PENELOPE那一行:执行@rownum := 0+1=1,然后LEAST(0,1)=0,此时@rownum变成1。 - 再处理原表中
NICK那一行:执行@rownum :=1+1=2,然后LEAST(0,2)=0,此时@rownum变成2。
- 先处理原表中
- 排序的第一关键字是
- 最后输出
SELECT列表的内容:
排序后的结果是NICK在前、PENELOPE在后,但@rownum的数值是排序时处理行的顺序留下的——PENELOPE是第一个被处理的行,所以它的rownum是1;NICK是第二个被处理的,所以rownum是2,这就对应上了你看到的结果。
一句话总结这个表达式的作用
LEAST(0, @rownum := @rownum+1)本质上是个“障眼法”:它不会改变原本按first_name排序的逻辑(因为LEAST结果都是0,不影响排序优先级),但能强制在排序过程中执行@rownum的自增操作,配合WHERE @rownum <=1就能限制返回的行数。
内容的提问来源于stack exchange,提问作者Ticks
相关产品推荐
相关产品推荐

