HAVING和WHERE有什么区别?


260

我必须以错误的方式进行谷歌搜索,否则我的时间很蠢。

什么之间的区别HAVING,并WHERESQL SELECT声明中?

编辑:我已经标记了史蒂文的答案是正确的答案,因为它包含链接上信息的关键点:

GROUP BY不使用时,HAVING就像一个WHERE条款

我所见过的WHERE情况并没有发生,GROUP BY而这正是我开始困惑的地方。当然,除非您知道这一点,否则无法在问题中指定它。


43
您引用的行根本不是关键。如wcm所指出的,关键位HAVING是后聚合过滤器,而是WHERE前聚合过滤器。
Nick Chammas 2012年

这个链接比下面的所有评论帮助我更好地理解了它,以为有人可以从此codeproject.com/Articles/25258/…
Lijin Durairaj

Answers:



368

HAVING:用于在聚合发生检查条件。
WHERE:用于在聚合发生之前检查条件。

这段代码:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City

为您提供马萨诸塞州所有城市的表格以及每个城市的地址数量。

这段代码:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City
Having Count(1)>5

为您提供马萨诸塞州的城市表,其中包含5个以上的地址以及每个城市的地址数。


7
这应该是公认的答案。“具有”和“何处”之间的区别使这一点立即变得清楚。
保罗

27

对我来说,第一大区别是:如果HAVING从SQL语言中删除,那么生活将像以前一样或多或少地持续下去。当然,少数派查询将需要使用派生表,CTE等进行重写,但是这样可以使它们更易于理解和维护。也许需要重写供应商的优化器代码以解决此问题,这也是行业内改进的机会。

现在考虑一下WHERE从该语言中删除。这次,将需要重写现有的大多数查询,而没有明显的替代结构。编码人员必须具有创造力,例如,DUAL使用该ON子句模拟上一个子句,对已知包含正好一行的表进行内部联接(例如在Oracle中)WHERE。这种结构是人为设计的;很明显,该语言中缺少某些内容,因此情况将变得更糟。

TL; DR我们HAVING明天可能会输掉,情况不会更糟,可能会更好,但是不能说同样的话WHERE


从这里的答案看来,许多人似乎没有意识到没有HAVING子句就可以使用GROUP BY子句。在这种情况下,该HAVING子句将应用于整个表表达式,并要求仅常量出现在该SELECT子句中。通常,该HAVING条款将涉及汇总。

这比听起来要有用。例如,考虑使用此查询来测试该name列对于以下所有值是否唯一T

SELECT 1 AS result
  FROM T
HAVING COUNT( DISTINCT name ) = COUNT( name );

只有两种可能的结果:如果HAVING子句为true,则结果为包含值的单行1,否则结果为空集。


等于“ SELECT COUNT(DISTINCT name)= COUNT(name)FROM T”吗?
MSpreij

@MSpreij不知道这是否对您有用,但是它在SQL Server 2005上不起作用,但是第一个起作用
Joe Joe

22

HAVING子句已添加到SQL,因为WHERE关键字不能与聚合函数一起使用。

查看此w3schools链接以获取更多信息

句法:

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value

这样的查询:

SELECT column_name, COUNT( column_name ) AS column_name_tally
  FROM table_name
 WHERE column_name < 3
 GROUP 
    BY column_name
HAVING COUNT( column_name ) >= 3;

...可以使用派生表(并省略HAVING)进行重写,如下所示:

SELECT column_name, column_name_tally
  FROM (
        SELECT column_name, COUNT(column_name) AS column_name_tally
          FROM table_name
         WHERE column_name < 3
         GROUP 
            BY column_name
       ) pointless_range_variable_required_here
 WHERE column_name_tally >= 3;

3
您稍微有点HAVING不明白这一点:之所以添加它,是因为没有将派生表添加到该语言中,并且直到它们成为SQL之前,它们之间的关系还不完整,并且不可避免地HAVING变得多余。
2011年

21

两者之间的区别在于与GROUP BY子句的关系:

  • WHERE在GROUP BY之前;SQL在对记录进行分组之前会先评估WHERE子句。

  • HAVING在GROUP BY之后;SQL对记录进行分组后评估HAVING。

选择语句图

参考资料


由于GROUP BY和HAVING都是可选的,因此该图显示了两种情况,只需遵循箭头即可。
Paul Sweatte '16

我对这个问题的回答的示例查询:SELECT 1 AS result FROM T HAVING...-在您的图中无法HAVING通过GROUP BY而无法访问,但是我完全有效和有用的查询没有GROUP BY。次要点:您无法选择在SELECT子句中包含文字值。
2016年

@onedaywhen既然您知道隐式GROUP BY,您为什么不提及它呢?您知道这种行为是否符合您的期望吗?
Paul Sweatte '16

我认为您是出于上下文引用我。问题是关于mySQL明显偏离Standard的问题,除了答案的最后一段以外,所有内容都描述了Standard的行为,最后暗示“ 其他答案中提到的隐式GROUP BY子句”。您是说图表旨在描述(所有)隐式行为吗?仅仅坚持需要编写的代码以获得所需的行为,是否会更有用?
2016年

...我不知道您在第二个链接中提到的行为。理想的结果是您修复了图以显示我提到的有效(显式)路径。想一想:该图涵盖了整个查询,但问题仅是对该WHERE->HAVING部分感兴趣,因此我认为值得密切注意细节。如果您认为我的答案有误,请对其进行编辑或在评论中提出建议的更正。
2016年

12

HAVING在使用汇总(如)时使用GROUP BY

SELECT edc_country, COUNT(*)
FROM Ed_Centers
GROUP BY edc_country
HAVING COUNT(*) > 1
ORDER BY edc_country;

8

应用WHERE作为对SQL返回的集合的限制;它使用SQL的内置集合运算和索引,因此是筛选结果集的最快方法。尽可能始终使用WHERE。

对于某些聚合过滤器,必须具有HAVING。它在sql检索,组合和排序结果之后过滤查询。因此,它比WHERE慢得多,应该避免使用,除非在需要的情况下。

即使WHERE更快,SQL Server仍可让您摆脱使用HAVING的麻烦。不要这样


对SQL语言中派生表的支持意味着您的断言“某些聚合过滤器必须具有HAVING”是错误的。
2011年

1
那是个很好的观点。自从我写了这个答案以来的三年中,我当然已经迁移到使用派生表,而以前是使用HAVING的。我还没有考虑过HAVING是否还有一些有意义的用例的问题。我也不知道派生表是否普遍比HAVING更好。
davidcl 2011年

7

WHERE子句不适用于聚合函数
意味着:不应使用这种奖励:表名

SELECT name  
FROM bonus  
GROUP BY name  
WHERE sum(salary) > 200  

在这里不必使用WHERE子句,而必须使用HAVING ..

不使用GROUP BY子句,HAVING子句仅用作WHERE子句

SELECT name  
FROM bonus  
GROUP BY name  
HAVING sum(salary) > 200  

3

黑白WHEREHAVING子句的区别:

WHEREHAVING子句之间的主要区别是,WHERE用于行操作和HAVING列操作。

为什么需要HAVING条款?

众所周知,聚合函数只能在列上执行,因此我们不能在WHERE子句中使用聚合函数。因此,我们在HAVING子句中使用聚合函数。


1

在汇总查询中,(在使用汇总函数的任何查询中)在生成汇总中间结果集之前先评估where子句中的谓词,

Haven子句中的谓词在生成后将应用于聚合结果集。这就是为什么汇总值的谓词条件必须放在Haveing子句中而不是Where子句中的原因,并且为什么可以在Haveing子句中而不是Where子句中使用Select子句中定义的别名。


1

我遇到了问题,发现WHERE和之间的另一个区别HAVING。它对索引列的作用不同。

WHERE my_indexed_row = 123 将显示行并在其他索引行上自动执行“ ORDER ASC”。

HAVING my_indexed_row = 123 显示从最旧的“插入”行到最新的所有内容,无顺序。


您如何知道这是两者之间的明确区别,而不是您正在使用的特定SQL Server的实现意外?
JdeBP '19

我刚刚在MariaDB上进行了测试。我猜这是八年前我使用的SQL Server产生了不同的结果。
Simmoniz

1

GROUP BY不使用when时,WHEREand HAVING子句实质上是等效的。

但是,何时GROUP BY使用:

  • WHERE子句用于从结果中过滤记录。过滤在进行任何分组之前进行。
  • HAVING子句用于从组中过滤值(即,在执行聚合到组后检查条件)。

来自这里的资源


具有和在哪里基本上不是等价的。执行时会报错。在HAVING子句中无效,因为它不在聚合函数或GROUP BY子句中。
Nagendra Kumar

1

一种考虑方式是,having子句是where子句的附加过滤器。

使用WHERE子句从结果中过滤记录。过滤在进行任何分组之前发生。甲HAVING子句用于过滤器的值从一组


0

这里

SQL标准要求HAVING必须仅引用GROUP BY子句中的列或聚合函数中使用的列

与应用于数据库行的WHERE子句相反


Source说:“已弃用列位置,因为该语法已从SQL标准中删除。” 令人遗憾的是,这是错误的:没有从标准中删除任何内容,具有讽刺意味的是,为什么HAVING在派生表“弃用”数十年之后,我们仍然有几十年的历史。
一天的

稍微学究,但引用不正确,例如,考虑SELECT 1 FROM T HAVING COUNT(*) >= 1;-既不引用GROUP BY子句中的列(不引用),也不引用聚合函数中的列(查询根本不引用任何列)。
某一天

0

在进行项目时,这也是我的问题。如上所述,HAVING检查已找到的查询结果的条件。但是WHERE用于在查询运行时检查条件。

让我举一个例子来说明这一点。假设您有一个这样的数据库表。

usertable {int用户名,日期日期字段,int每日收入}

假设表中有以下几行:

1,2011-05-20,100

1,2011-05-21,50

1,2011-05-30,10

2,2011-05-30,10

2,2011-05-20,20

现在,我们想要得到的useridS和sum(dailyincome)sum(dailyincome)>100

如果我们写:

从用户表中选择userid,sum(dailyincome),sum(dailyincome)> 100 GROUP BY userid

这将是一个错误。正确的查询将是:

从用户表GROUP BY中选择用户ID,总和(每日收入)用户总和(每日收入)> 100


0

WHERE子句用于在基表中,比较值,而HAVING子句可用于过滤的聚集函数的计算结果的查询结果集的点击这里


-1

我使用HAVING来基于聚合函数的结果来约束查询。EG选择blahblahblah组中的*,因为SOMETHING具有count(SOMETHING)> 0


-1

可能“ where”的主题是一行,而“ have”的主题是一个群体。我对吗?


3
在发布答案之前,您应该确定。这可能会误导他人。
pippin1289
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.