HAVING子句是多余的吗?

时间:2012-08-25 10:19:23

标签: mysql sql group-by having having-clause

以下两个查询产生完全相同的结果:

select country, count(organization) as N
from ismember
group by country
having N > 50;

select * from (
  select country, count(organization) as N
  from ismember
  group by country) x
where N > 50;

每个HAVING子句都可以用子查询和这样的WHERE子句替换吗?或者是否存在HAVING条款绝对必要/更强大/更有效/无论什么情况?

6 个答案:

答案 0 :(得分:10)

这里有两个问题:第一个问题的答案是HAVING - 载入查询的结果集与执行的同一查询的结果集相同子查询,用WHERE子句装饰。

第二个问题是关于表现和表现力 - 在这里我们将大力投入实施。在MySQL上有一条细红线,性能开始分散:内部查询的结果集不能再保留在内存中。在这种情况下,MySQL将创建内部查询的磁盘表示,然后在其上使用WHERE选择器。如果使用HAVING子句,则不会发生这种情况,将从结果集中删除被取消资格的组。

这意味着,HAVING子句的选择性越高,它具有的性能相关性越高:考虑内部查询的一百万行的结果集,即由HAVING子句减少到5行 - 内部查询的结果集很可能不会保存在内存中,但很可能是最终结果集。

修改

我有过一次:查询从一个非常均匀分布的表中选择了几个异常值(每天在一个研讨会中的物理机器上生成的件数)。我调查是因为IO负载很高。

修改2

请记住,查询缓存用于子查询 - 恕我直言,地方开发应该更多地关注 - 所以子查询模式不会从内部查询作为缓存结果集中获益

答案 1 :(得分:8)

在Sql Server 2008中,两个类似的查询具有完全相同的执行计划:

enter image description here

我还研究了很多由Entity Framework生成的查询(使用SS 2008),到目前为止,我从未见过带有HAVING子句的查询。使用聚合结果上的条件对查询进行分组始终会转换为带有子查询的查询。我相信ADO.Net团队知道他们正在做......

答案 2 :(得分:4)

HAVING子句对于避免增加子查询的复杂性非常有用。但是,这两者在逻辑上是等价的,并且每个HAVING子句都可以使用子查询重写。

如果您感到好奇,如果您准备将GROUP BY置于极端,您还可以将每个WHERE子句写为HAVING子句。

答案 3 :(得分:0)

恕我直言,使用HAVING子句应该是高效的,因为在第二种情况下,工作表上会有一个额外的传递,其中包含运行过滤条件的分组结果。

答案 4 :(得分:0)

我知道,你把它从一般改为MySQL,但我想在这里添加一个(可能有用)注释。 稍加修改后,我在SQL Server 2008中尝试了您的查询。

对于任何想要了解更多细节的人来说,两个查询的执行计划甚至是SQL Server 2008中的 完全相同的 。因此,优化器处理这两个命令以相同的方式和相同的表现和估计。

答案 5 :(得分:0)

逻辑上是的,结果将是相同的结果。但性能可能不同。 HAVING子句可能会导致DB更改不同的执行计划。

上述人员的注释(无法以某种方式直接评论) - 执行计划不仅取决于您的查询。它也可能由DB根据统计信息(如运行时的表大小等)进行调整。至少对DB2来说......