【问题标题】:filter SELECTed rows by HAVING by variables value changed in column description按列描述中更改的变量值过滤选择的行
【发布时间】:2012-11-29 09:28:22
【问题描述】:

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

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

【问题讨论】:

    标签: mysql variables select having


    【解决方案1】:

    @foundnow 不是每行变量。它继续存在。创建列ff 使其成为每行值。另外,来自the documentation

    在 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,设置@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 不关心该选择表达式中的内容。第二个引用结果集中的一列,因此必须知道该结果并执行选择。

    此外,如果可以使用WHERE,请尽量避免使用HAVING 子句,它们是非常首选。

    【讨论】:

    • 谢谢,就我而言,我无法避免拥有。我需要在特定条件下中断行获取(这里这个条件被简化为id=3)。所以,我需要 FIRST 查询,但发现了意外行为。
    • ...好吧,这就是它的工作原理,手册确实警告您:“作为一般规则,您永远不应该为用户变量赋值并在相同的语句。” ...对您来说更令人震惊的是:“涉及用户变量的表达式的计算顺序是未定义的,并且可能会根据给定语句中包含的元素而改变;此外,此顺序不保证在 MySQL 服务器的版本之间是相同的” 如果您可以详细说明您使用 HAVING 的实际条件/查询,也许我们可以弄清楚。
    • 谢谢。那么,在条件(HAVING 或 WHERE)中使用相同的变量并在任何地方分配新值(我们可以在 HAVING 闭包中更改)是个坏主意吗?所以没有合适的方法来“打破”在某些条件下获取的行?
    • 几乎是的。不过,通常 一种方法可以将其重写为(通常甚至是无变量)WHERE... 但是如果没有您的实际查询和数据结构,很难说。你最后的例子只是LIMIT 10, some_very_large_number,我假设你的实际查询更复杂..
    • 我需要选择具有最大 id 的行,受 size 字段的 SUM 限制 SET @enough=0; SELECT id, (@enough:=@enough+size) as ff FROM ometable HAVING @enough
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 2016-06-30
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    • 2014-11-19
    相关资源
    最近更新 更多