对于非聚合分组列,是否需要?

时间:2016-09-06 19:25:14

标签: mysql sql

我有一些生成SQL的代码,需要了解HAVING是否对非聚合分组列有必要(或有用)?我没有找到任何表明它的例子,但想在这里查看。

MySQL文档有这样的评论“SQL标准要求HAVING必须仅引用GROUP BY子句中的列或聚合函数中使用的列。”

我知道HAVING对于组上的聚合条件是必要的,并且还理解WHERE可以用于非聚合的分组列(这可能比具有更高效率),但我的问题是:

非聚合分组列是否必要(或有用)?

由于

2 个答案:

答案 0 :(得分:4)

HAVING专为聚合列而设计。 MySQL允许HAVING子句中的非聚合列。有三个用例,我可以想到:

  1. 效率黑客,当组的值具有相同的组值时。
  2. 应该避免的错误。
  3. 当没有聚合时效率黑客。
  4. 第一个可以想象在这样的情况下使用:

    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。如果没有使用聚合列,则无论如何都要基于单行值进行选择,因此唯一的(语义)差异是在分组之前还是之后选择行 - 但结果将是相同的。

(请注意,这种差异在实践中可能不成立,优化程序可能会重新排序操作。)