使用HAVING和子查询有什么区别

时间:2018-04-11 07:27:49

标签: sql subquery where-clause having

我是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; 

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

4 个答案:

答案 0 :(得分:2)

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

汇总数据时可以使用HAVING,例如:

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

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

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

答案 1 :(得分:2)

HAVING通常用于限制GROUP BY子句的结果,与使用WHERE限制SELECT子句的结果的方式相同。

此外,虽然WHERE子句不能直接包含聚合,但您可以使用HAVING子句(使用聚合),也可以使用{{1}中的子查询包含聚合的子句。

除非您正在对数据进行分组或以其他方式对其进行聚合,否则我无法理解您为什么要将WHERE子句重写为WHERE子句。

在您的示例中,您将基于A,B,C和Year创建一组组。那么,你是将那些群体限制在群体的预期寿命(无论这是什么意思?)大于同一群体的平均预期寿命乘以1.15的群体。它没有任何意义,这是你已经建立的。

答案 2 :(得分:1)

您可以使用子查询使用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 :(得分:0)

我的两分钱

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

count

回到您的问题,您尝试基于几乎所有列创建组,这样您最终的组数几乎等于表中的行数(即每个组只有一行),然后您尝试在 select department, Avg(salary) from employee group by department having count(*) > 10; 子句中执行聚合函数 AVG,如上所述,该聚合函数的范围仅限于一个组。每组只有一行。因此,这就像您试图获取一个现在只有一行(因为您几乎包含 group by 子句中的所有列)的组(或多个组),其中 column: having 使用条件(在 {{1} } 子句):x = 10,因此您不会在提取查询中获得任何数据。