【问题标题】:What is the difference between HAVING and WHERE in SQL?SQL中的HAVING和WHERE有什么区别?
【发布时间】:2010-09-22 04:42:05
【问题描述】:

SQL SELECT 语句中的HAVINGWHERE 有什么区别?

编辑:我已将 Steven 的答案标记为正确答案,因为它包含链接上的关键信息:

当不使用GROUP BY 时,HAVING 的行为类似于WHERE 子句

我看到WHERE 没有GROUP BY 的情况是我开始困惑的地方。当然,在您知道这一点之前,您不能在问题中指定它。

【问题讨论】:

  • 你引用的那行根本不是关键。关键位 as wcm pointed outHAVING 是一个聚合后过滤器,而 WHERE 是一个预聚合过滤器。
  • 这个链接比下面的所有 cmets 更能帮助我理解它,认为有人可以通过这个codeproject.com/Articles/25258/…得到帮助
  • 另外,请考虑使用不带GROUP BYHAVING 代替WHERE 在Oracle 等所有数据库中并不普遍。

标签: sql where-clause having


【解决方案1】:

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

为您提供 MA 中超过 5 个地址的城市表以及每个城市的地址数。

【讨论】:

  • 这应该是公认的答案。 “拥有”和“在哪里”之间的区别使这一点立即变得清晰。
【解决方案2】:

HAVING 指定一个搜索条件 SELECT 语句中使用的组或聚合函数。

Source

【讨论】:

    【解决方案3】:

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

    现在考虑一下从语言中删除WHERE。这一次,存在的大部分查询需要在没有明显替代构造的情况下重写。编码员必须要有创造力,例如使用ON 子句模拟之前的WHERE 子句,对已知仅包含一行的表进行内部连接(例如,Oracle 中的DUAL)。这种结构是人为的;很明显,语言中缺少某些东西,结果情况会更糟。

    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 子句为真,则结果为包含值1 的单行,否则结果将为空集。

    【讨论】:

    • 这是否等同于“SELECT COUNT(DISTINCT name) = COUNT(name) FROM T”?
    • @MSpreij 不知道这是否适合您,但它不适用于 SQL Server 2005,但第一个可以
    【解决方案4】:

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

    查看此w3schools link 了解更多信息

    语法:

    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;
    

    【讨论】:

    • 您稍微漏了点:添加了HAVING 是因为派生表尚未添加到语言中,直到它们是 SQL 才关系完整,一旦它们不可避免地成为 HAVING多余的。
    【解决方案5】:

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

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

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

    参考文献

    【讨论】:

    • 由于 GROUP BY 和 HAVING 都是可选的,所以图表显示了这两种情况,只需按照箭头。
    • 我对这个问题的回答中的示例查询:SELECT 1 AS result FROM T HAVING... - 在您的图表中,如果不通过GROUP BY,我无法到达HAVING,但我完全有效且有用的查询没有@987654330 @。次要观点:您无法选择在 SELECT 子句中包含文字值。
    • @onedaywhen 既然you know 关于隐含的 GROUP BY,为什么不提呢?你知道this behavior 是不是你所期待的吗?
    • 我认为你是在断章取义地引用我的话。问题是关于 mySQL 与标准的明显偏差,除了我回答的最后一段之外,所有内容都描述了标准的行为,最后一段提到“隐含的 GROUP BY 子句在其他答案中提到”。您是说您的图表旨在描述(所有)隐式行为吗?只坚持你需要编写的代码来获得所需的行为不是更有用吗?
    • ...我不知道您在第二个链接中暗示了什么行为。期望的结果是您修复图表以显示我提到的有效(显式)路径。想一想:该图涵盖了整个查询,但问题只对WHERE-&gt;HAVING 部分感兴趣,所以我认为值得密切关注细节。如果您认为我的回答有误,请对其进行编辑或在 cmets 中发布建议的更正。
    【解决方案6】:

    HAVING 用于当您使用 GROUP BY 等聚合时。

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

    【讨论】:

      【解决方案7】:

      WHERE 被应用为对 SQL 返回的集合的限制;它使用 SQL 的内置集合操作和索引,因此是过滤结果集的最快方法。尽可能使用 WHERE。

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

      即使 WHERE 更快,SQL Server 也可以让您轻松使用 HAVING。不要这样做。

      【讨论】:

      • 支持 SQL 语言中的派生表意味着您的断言“某些聚合过滤器需要 HAVING”是错误的。
      • 这是一个很好的观点。自从我写下这个答案以来的三年里,我当然已经转向使用派生表,而我以前会使用 HAVING。我还没有考虑过 HAVING 是否仍然有一些有意义的用例的问题。我也不知道派生表的性能是否普遍优于 HAVING。
      【解决方案8】:

      WHERE 子句不适用于聚合函数
      意思是:你不应该这样使用 奖励:表名

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

      HERE 而不是使用 WHERE 子句,您必须使用 HAVING..

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

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

      【讨论】:

        【解决方案9】:

        WHEREHAVING 子句的区别:

        WHEREHAVING 子句的主要区别在于,WHERE 用于行操作,HAVING 用于列操作。

        为什么我们需要HAVING 子句?

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

        【讨论】:

          【解决方案10】:

          一种理解方式是,have 子句是 where 子句的附加过滤器。

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

          【讨论】:

            【解决方案11】:

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

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

            【讨论】:

              【解决方案12】:

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

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

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

              【讨论】:

              • 您怎么知道这是两者之间的定义差异,而不是您使用的特定 SQL 服务器的意外实现?
              • 我刚刚在 MariaDB 上进行了测试。我猜是我 8 年前使用的 SQL 服务器产生了不同的结果。
              【解决方案13】:

              当不使用GROUP BY 时,WHEREHAVING 子句本质上是等价的。

              但是,当使用GROUP BY 时:

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

              来自Here的资源

              【讨论】:

              • 拥有和在哪里本质上是不等价的。执行时会报错。在 HAVING 子句中无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。
              【解决方案14】:

              来自here

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

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

              【讨论】:

              • 消息来源说,“不推荐使用列位置,因为语法已从 SQL 标准中删除。”遗憾的是,这是错误的:标准中从未删除任何内容,具有讽刺意味的是,这就是为什么在派生表“弃用”几十年后我们仍然拥有HAVING 的原因。
              • 有点迂腐,但引用不正确,例如考虑SELECT 1 FROM T HAVING COUNT(*) &gt;= 1; - 不引用GROUP BY 子句中的列(没有),也不引用聚合函数中的列(查询根本不引用列)。
              【解决方案15】:

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

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

              usertable{ int userid, date datefield, int dailyincome }

              假设表中有以下行:

              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)&gt;100

              如果我们写:

              SELECT userid, sum(dailyincome) FROM usertable WHERE sum(dailyincome)>100 GROUP BY userid

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

              SELECT userid, sum(dailyincome) FROM usertable GROUP BY userid HAVING 总和(每日收入)>100

              【讨论】:

                【解决方案16】:

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

                【讨论】:

                  【解决方案17】:

                  当不使用 GROUP BY 时,WHERE 和 HAVING 子句本质上是等价的。

                  但是,当使用 GROUP BY 时:

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

                  【讨论】:

                    【解决方案18】:

                    我使用 HAVING 来限制基于聚合函数结果的查询。例如。选择 * 在 blahblahblah 组中的某物有 count(SOMETHING)>0

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2019-04-29
                      • 2011-11-18
                      • 2017-10-07
                      • 2013-11-25
                      • 2019-12-09
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      相关资源
                      最近更新 更多