有人能解释一下以下两个请求之间的区别吗?
SET @foundnow=0;
SELECT id, (@foundnow:=IF(`id`=3,1,0)) as ff
FROM `sometable`
HAVING @foundnow=0
result is
id ff
1 0
2 0
3 1
和
SET @foundnow=0;
SELECT id, (@foundnow:=IF(`id`=3,1,0)) as ff
FROM `sometable`
HAVING ff=0
result is
id ff
1 0
2 0
4 0
5 0
...
为什么首先给出id=3(包括)的所有行,其次给出id=3以外的所有行?
我想与这个问题相关的是以下请求的“意外”行为
SET @tot=0;
SELECT @tot:=@tot+1 as `ff`
FROM `anytable`
HAVING (`ff`>10)
它给出了ff=12,14,16,18的行…
最佳答案
@foundnow
不是每行变量。它还活着。创建一个列ff
会使它成为每行值。另外,从the documentation开始:
在select语句中,每个select表达式仅在发送到客户端时计算。这意味着,在HAVING、GROUP BY或ORDER BY子句中,引用在“选择表达式”列表中被赋值的变量时,不能按预期工作:
这意味着你的第一个例子是:
1:需要@foundrow,则为0,因此发送,将@foundrow设置为新值(0)
2:如果需要@foundrow,则为0,因此发送,将@foundrow设置为新值(0)
3:需要@foundrow,则为0,因此发送,将@foundrow设置为新值(1)
3:有需要@foundrow,是1,不要发送
4:有需要@foundrow,是1,不要发送
5:有需要@foundrow,是1,不要发送
等。。。
你的第二步是:
1:需要ff时,执行select,set@foundrow,set ff(=不再@foundrow)=send
2:需要ff时,执行select,set@foundrow,set ff(=不再@foundrow)=send
3:需要ff时,执行select,set@foundrow,set ff(=不再@foundrow)=不发送
4:需要ff时,执行select,set@foundrow,set ff(=不再@foundrow)=send
因此,如果@foundrow,第一个示例根本不计算表达式!=0,因为@foundrow是已知的,而mysql不关心该select表达式中的内容。第二个引用resultset中的列,因此必须知道该结果,并执行select。
此外,如果可以使用HAVING
子句,请尽量避免使用WHERE
子句,因为它们非常受欢迎。
关于mysql - 通过HAVING按列描述中更改的变量值过滤SELECT行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13826842/