【问题标题】:What is the difference of using HAVING vs a subquery使用 HAVING 与子查询有什么区别
【发布时间】:2018-09-20 23:30:42
【问题描述】:

我是 SQL 新手,通过数据营学习。我想知道您是否可以使用“HAVING”获得与嵌套“WHERE”子句相同的结果。

相关:SQL - having VS where 我了解 HAVING 与 min、max、.. 等聚合函数一起使用。

如何用 HAVING 重写以下内容?:

SELECT *
FROM populations
WHERE year = 2015 AND life_expectancy >(
   SELECT AVG(life_expectancy)*1.15
   FROM populations
);

假设我在“人口”表中有 6 列:A(字符)、B(字符)、C(字符)、D(数字,即示例中的 life_expectancy)、年份和 E(数字)。

我尝试了以下方法:

SELECT *
FROM populations
WHERE year = 2015
GROUP BY A, B, C, year
HAVING life_expectancy > AVG(life_expectancy)*1.15; 

但是,这会返回一个空表。我意识到这不是一个可重复的例子,但也许对它为什么不起作用的一般解释就足够了:)

【问题讨论】:

  • 坚持你的子查询,没有错。
  • @Anonymous 该查询还有另一个问题:SELECT * ... GROUP BY A,B,C, year。除非所有其他列在功能上依赖于 A、B、C、年份并且我猜它们不是,否则查询将仅在禁用 ONLY_FULL_GROUP_BY 的 MySQL 上工作。 More

标签: sql subquery where-clause having


【解决方案1】:

我的两分钱

Group By 允许您从完整的结果集中创建组,以便您可以执行一些操作(聚合函数),其(操作')范围仅限于该组,having 让您摆脱(或包括)基于您在 having 关键字之后放置的条件的几个组,并且该条件也可以是聚合函数。 此外,您可以在每个组上执行不同的聚合函数(在select 子句中),并在having 子句中使用不同的聚合函数来过滤掉几个组。 例如假设您有员工及其部门数据,并且您想计算每个部门的平均工资,但如果该部门的员工少于 10 人,则不考虑该部门。 在这里,您必须根据部门将所有员工分成不同的组,这是由group by 子句完成的,然后您将执行average 操作,其范围仅限于每个组。但是在对每个组执行平均操作之前,您希望排除员工人数少于 10 人的组(即部门),为此,您将在 having 子句中使用不同的聚合操作(即 count)并且 count 聚合操作再次仅限于每个组。 例如

select 
department, Avg(salary) from employee 
group by department 
having count(*) > 10;

回到您的问题,您尝试根据几乎所有列进行分组,这样您最终的组数几乎等于表中的行数(即每个组只有一行),然后您尝试在having 子句中执行聚合函数AVG,如上所述,该聚合函数的范围仅限于一个组。每组只有一排。因此,就像您正在尝试获取一个(或多个)组,该组现在只有一行(因为您在 group by 子句中包含几乎所有列)列:x = 10 使用条件(在having 子句中): x > 10,因此您不会在 fetch 查询中获得任何数据。

【讨论】:

    【解决方案2】:

    您可以使用子查询重写带有 HAVING 的查询。例如;

    SELECT country, sum(population) sum_pop
      FROM cities
     GROUP BY country HAVING sum(population) > 100000
     ORDER BY sum(population) DESC;
    

    相当于:

    SELECT country, sum_pop
      FROM (SELECT country, sum(population) sum_pop
              FROM cities
             GROUP BY country) subquery
     WHERE sum_pop > 100000
     ORDER BY sum_pop DESC;           
    

    【讨论】:

      【解决方案3】:

      HAVING 通常用于限制GROUP BY 子句的结果,就像WHERE 用于限制SELECT 子句的结果一样。

      此外,虽然WHERE 子句不能直接包含聚合,但您可以使用HAVING 子句(带有聚合),或者您可以在包含聚合的WHERE 子句中使用子查询.

      除非您对数据进行分组或以其他方式对其进行聚合,否则我看不出您为什么要将 WHERE 子句重写为 HAVING 子句。

      在您的示例中,您正在创建一组基于 A、B、C 和年份的组。然后,您将这些组限制为组的预期寿命(无论这意味着什么?)大于同一组的平均预期寿命乘以 1.15 的组。这没有任何意义,这是你已经建立的。

      【讨论】:

      • 检查你的第一句话。 HAVING 旨在允许基于聚合信息过滤结果。在having子句中过滤未聚合的数据效率不高,因为这应该在分组之前完成。
      • 您的整个答案似乎正确地暗示了 Have 专门用于聚合函数,除了您的第一句话。
      • 已更新...希望我已经消除了我最初造成的一些混乱。
      【解决方案4】:

      HAVING 对结果起作用,子查询是一个单独的查询。在您的示例中,您计算​​的平均值适用于整个表格。在 HAVING 子句中,它影响形成结果行的数据集。所以在这种情况下,它基本上意味着你想要一个大于自身乘以 1.15 的值,这当然是行不通的。

      HAVING 在您聚合数据时可用,例如:

      SELECT country, sum(population) FROM cities
      GROUP BY country
      HAVING sum(population) > 100000
      

      这会按国家/地区对所有城市进行分组,然后仅返回城市人口总和大于该值的行。

      因此,子查询和 HAVING 有非常不同的用例,并且您的查询不能转换为 HAVING,因为您不尝试比较组内的值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-09-15
        • 1970-01-01
        • 2016-02-15
        • 2010-09-22
        • 1970-01-01
        • 2019-11-10
        • 2011-11-18
        • 1970-01-01
        相关资源
        最近更新 更多