使用 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
,因此您不会在提取查询中获得任何数据。
我是 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
,因此您不会在提取查询中获得任何数据。