在HAVING子句之后使用WHERE子句是可能的吗?

20

在HAVING子句之后使用WHERE子句是否可行?

我首先想到的是子查询,但我不确定。

附言:如果答案是肯定的,能给出一些示例吗?


3
这是一个诡计/面试问题,还是你真的需要解决一个实际问题? - itsadok
1
是的。这个问题来自一次面试。 - cc.
5个回答

35

不,不能在同一个查询中。

where子句应该放在havinggroup by之前。如果您想在分组之前过滤记录,则条件放在where子句中;如果您想要过滤分组记录,则条件放在having子句中:

select ...
from ...
where ...
group by ...
having ...

如果因为某种怪异的原因,以上两种方法都不可用,那么你必须将查询变成子查询,以便你可以将where子句放在外部查询中:

select ...
from (
   select ...
   from ...
   where ...
   group by ...
   having ...
) x
where ...

5

HAVING子句就是在GROUP BY之后的WHERE子句。为什么不将WHERE条件放在HAVING子句中呢?


从概念上讲,HAVING子句是在GROUP BY操作之后应用的,而WHERE子句是在之前应用的,因此理论上可以通过在WHERE子句中进行“过滤”来进行优化。实际上,您需要(像往常一样)查看优化器处理它的方式,例如检查执行计划。还要考虑人类读者,他们通常希望在WHERE子句中看到“过滤”谓词(而不是连接子句、HAVING子句等)。 - onedaywhen

5
如果这是一个诡计问题,如果WHERE和HAVING不在同一级别,那么使用子查询是有可能的,就像你提到的那样。
我认为类似下面的语句可以工作:
HAVING value =(SELECT max(value)FROM foo WHERE crit = 123)
附注:你为什么要问?你有具体的问题吗?
附注2:哦,我错过了“interview*”标签。。。

3

从SELECT帮助

WHERE、GROUP BY和HAVING子句的处理顺序以下步骤显示了带有WHERE子句、GROUP BY子句和HAVING子句的SELECT语句的处理顺序:

FROM子句返回初始结果集。

WHERE子句排除不符合其搜索条件的行。

GROUP BY子句将所选行收集到每个GROUP BY子句中唯一值的一个组中。

在选择列表中指定的聚合函数为每个组计算摘要值。

HAVING子句还将排除不符合其搜索条件的行。

因此,你不能。


2

在同一范围内,答案是否定的。如果允许使用子查询,则可以完全避免使用HAVING

我认为HAVING是一个过时的东西。Hugh Darwen将HAVING称为“结构化查询的愚蠢”:

In old SQL, the WHERE clause could not be used on results of aggregation, so they had to invent HAVING (with same meaning as WHERE):

SELECT D#, AVG(Salary) AS Avg_Sal
  FROM Emp
 GROUP 
    BY D#
HAVING AVG(Salary) > 999;

But would we ever have had HAVING if in 1979 one could write:

SELECT * 
  FROM (
        SELECT D#, AVG(Sal) AS Avg_Sal
          FROM Emp
         GROUP 
            BY D# 
       )
      AS dummy
WHERE Avg_Sal > 999;
我强烈怀疑对于达温的问题,答案是否定的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接