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

What is the difference of using HAVING vs a subquery

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

假设我在 table '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; 

然而,这returns一个空table。我意识到这不是一个可重现的例子,但也许对它为什么不起作用的一般解释就足够了:)

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

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

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

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

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

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

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

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

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

您可以使用子查询重写具有 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;           

我的两毛钱

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

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

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