3

谁能解释以下两个请求之间的区别:

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 的行...

4

1 回答 1

1

@foundnow不是每行变量。它继续存在。创建列ff使其成为每行值。另外,从文档中

在 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,不发
  • ETC...

你的第二个是这样的:

  • 1:需要ff,执行select,设置@foundrow,设置ff(=不再@foundrow)=发送
  • 2:需要ff,执行select,设置@foundrow,设置ff(=不再@foundrow)=发送
  • 3:有需要ff,执行select,设置@foundrow,设置ff(=不再@foundrow)=不发送
  • 4:需要ff,执行select,设置@foundrow,设置ff(=不再@foundrow)=发送

因此,如果@foundrow!=0,第一个示例根本不计算表达式,因为@foundrow 是已知的,MySQL 不关心该选择表达式中的内容。第二个引用结果集中的一列,因此必须知道该结果并执行选择。

HAVING此外,如果可以使用's,请尽量避免使用子句,WHERE它们是非常受欢迎的。

于 2012-12-11T19:32:41.400 回答