我有一些生成SQL的代码,需要了解HAVING是否对非聚合分组列有必要(或有用)?我没有找到任何表明它的例子,但想在这里查看。
MySQL文档有这样的评论“SQL标准要求HAVING必须仅引用GROUP BY子句中的列或聚合函数中使用的列。”
我知道HAVING对于组上的聚合条件是必要的,并且还理解WHERE可以用于非聚合的分组列(这可能比具有更高效率),但我的问题是:
非聚合分组列是否必要(或有用)?
由于
答案 0 :(得分:4)
HAVING
专为聚合列而设计。 MySQL允许HAVING
子句中的非聚合列。有三个用例,我可以想到:
第一个可以想象在这样的情况下使用:
select l.*, sum(x.y)
from list l join
. . .
group by l.listid
having l.foo = 'bar';
这是有效的,因为所有l.foo
应该具有给定l.listid
的相同值(假设l.listid
是主键)。在这种情况下,这会像使用where
一样过滤数据。
但是,如果这个条件不成立,则HAVING
/ WHERE
等价不成立。 HAVING
将从不确定的行中选择一个值,然后过滤生成的聚合列。 WHERE
在聚合之前进行过滤。因此,如果列表可以具有相同的类型,那么:
select l.*, sum(x.y)
from list l join
. . .
group by l.type
having l.foo = 'bar';
这是一个格式错误的查询(因此我认为是错误),但并不等同于将条件移至WHERE
。
第三种情况是没有聚合:
select l.*, concat('a', 'b', 'c') as test
from list l
having test = 'abc';
这是MySQL的一个便利。其他方言将使用子查询。 MySQL实现子查询,导致效率低下。
答案 1 :(得分:1)
没有
在对行进行分组之前应用 WHERE
条件,对分组的行应用HAVING
。如果没有使用聚合列,则无论如何都要基于单行值进行选择,因此唯一的(语义)差异是在分组之前还是之后选择行 - 但结果将是相同的。
(请注意,这种差异在实践中可能不成立,优化程序可能会重新排序操作。)