SQL中的WHERE子句中为啥不允许应用聚集函数呢?请通俗的解释一下或者谈谈自己的见解!

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL中的WHERE子句中为啥不允许应用聚集函数呢?请通俗的解释一下或者谈谈自己的见解!相关的知识,希望对你有一定的参考价值。

聚合函数要与group by语句一并使用(若select中仅有聚合函数列,group by可省略)
group by的作用就是分组,只有把数据进行分组后才可以用聚合函数求值
而group by是一个分界点,分隔where与having的,按照sql语句的执行顺序
当执行where时,数据尚未执行group by,无法分组,就不能使用聚合函数
而当执行having时,数据已经按照group by执行了分组,即可使用聚合函数
顺便一提,select的执行顺序在having之后
参考技术A

Where是一个约束声明,使用Where来约束从数据库查询的范围Where是在结果返回之前起作用的。

select和having都可以添加聚合函数,这是由sql的执行顺序决定的。

sql执行顺序如下:

from--where---group by --having---select ---order by --limit

先执行from部分,知道从哪个表提取数据,然后执行where对条件进行限,然后通过groupby进行聚合,然后通过having对聚合后的结果进行过滤,再利用select把数据查询出来, 然后通过order by 对数据进行排序,通过limit找出前几位。

参考技术B 命令还没有执行,聚 集函数还没有形成字段,它去哪儿找这个聚集函数呢?追问

但是SELECT和HAVING语句都可以使用聚集函数啊,有什么区别呢?

追答

我也不太会用SELECT语句,
找到一点线索,说 WHERE不能用聚集函数, HAVING可以用,你参考一下
http://hi.baidu.com/fegro/item/cbc6c5cd0f430c03c710b29f

又查了一点 :理解聚集和SQL的 WHERE 以及 HAVING 子句之间的关系对我们非常重要。 WHERE 和 HAVING 的基本区别如下: WHERE 在分组和聚集计算之前选取输入行(因此,它控制哪些行进入聚集计算), 而 HAVING 在分组和聚集之后选取分组的行。 因此,WHERE 子句不能包含聚集函数; 因为试图用聚集函数判断那些行输入给聚集运算是没有意义的。 相反,HAVING 子句总是包含聚集函数。

本回答被提问者和网友采纳

为啥 where 子句中不允许使用聚合函数

【中文标题】为啥 where 子句中不允许使用聚合函数【英文标题】:Why are aggregate functions not allowed in where clause为什么 where 子句中不允许使用聚合函数 【发布时间】:2017-07-17 04:28:58 【问题描述】:

我正在寻求对此的澄清。我在下面写了两个查询:

我们有一个员工姓名表,其中包含 ID、姓名、工资等列

  1.  Select name from employee 
    where sum(salary) > 1000 ;

  2.  Select name from employee 
    where substring_index(name,' ',1) = 'nishant' ;

查询 1 无效,但查询 2 有效。根据我的开发经验,我觉得可能的解释是:

sum() 作用于参数中指定的一组值。这里 'salary' 列已通过,因此它必须将所有值相加 柱子。但是在 where 子句中,记录会被一一检查, 就像第一条记录 1 被检查以进行测试,依此类推。因此 sum(salary) 不会被计算,因为它需要访问所有列 值,然后只有它会返回一个值。

查询 2 作为 substring_index() 作用于单个值,因此在这里它作用于提供给它的值。

您能否验证我的理解。

【问题讨论】:

您认为查询 1 可以实现什么目标?你认为它做什么/应该做什么(用英语)?所以你想要每个“工资总和”高于 1000 的员工的姓名?但是每个员工只有一份工资,那么“工资总和”是什么意思呢? @ErwinBolwidt 如果代替 sum(),我使用的是 avg(),假设我想要薪水高于 avg() 的员工。我只想验证我为什么不能在 where 子句中使用聚合函数的解释。 @user3527008 - 您可以在having 子句中使用它们 @AlexPoole - 我读到这个问题的意思是,“为什么 SQL 的设计者需要限制聚合函数的使用,所以它们只能在 HAVING 子句中而不是 @987654324 @?他们不能出现在WHERE子句中是否有合理的原因?" 当然,一个更好的问题是“为什么不能有一个像 where sal = max(sal)where sal > avg(sal) 这样的 where 子句(即使没有 group by 子句 - 将所有行放在一个组)。正如我解释的那样,原因是这需要循环推理,因为 maxavg 并未应用于基表中的所有行;它们仅应用于满足 @987654332 的行@ 条件!如果整个基表需要maxavg,则必须在子查询中单独计算。 【参考方案1】:

不能在WHERE 子句中使用SUM() 的原因是子句的求值顺序。

FROM 告诉你从哪里读取行。在将行从磁盘读取到内存时,会检查它们是否符合WHERE 条件。 (实际上在许多情况下,WHERE 子句失败的行甚至不会从磁盘读取。“条件”正式称为 谓词,并且查询执行引擎使用一些谓词来决定从基表中读取哪些行。这些称为 access 谓词。)如您所见,WHERE 子句在呈现给引擎时应用于每一行。

另一方面,只有在读取了所有行(验证所有谓词)之后才进行聚合。

想一想:SUM() 仅适用于满足WHERE 条件的行。如果您将SUM() 放在WHERE 子句中,则您要求的是循环逻辑。新行是否通过WHERE 子句?我怎么会知道?如果会通过,那么我必须将其包含在SUM 中,但如果没有,则不应将其包含在SUM 中。那么我该如何评估SUM 条件呢?

【讨论】:

先生的解释太棒了。哇 如果您正在寻找解决方案,您可能需要做的就是将您的 WHERE 语句移动到 HAVING 子句中。 @deed02392 - 如果你在事实发生三年半后跳进去,也许你应该阅读这个问题,直到你首先理解它。 OP 想了解条件 必须HAVING 子句中而不是在 WHERE 子句中的理论原因。解决方案(与您提出的相同)很容易给出并为所有人所知。更微妙的问题是为什么只能这样做。您可能还想阅读 OP 问题下的 cmets,其中进一步澄清了此线程的目的。【参考方案2】:

为什么不能在where子句中使用聚合函数

聚合函数适用于数据集。 WHERE 子句不能访问整个集合,只能访问它当前正在处理的行。

你当然可以使用 HAVING 子句:

select name from employee 
group by name having sum(salary) > 1000;

如果必须使用WHERE,可以使用子查询:

select name from (
    select name, sum(salary) total_salary from employee
    group by name
) t where total_salary > 1000;

【讨论】:

正是我想要的!!!只是标题需要编辑:D。但再次感谢:)【参考方案3】:

sum() 是一个聚合函数。通常,您希望它可以与group by 一起使用。因此,您的第一个查询缺少group by。在group by 查询中,having 用于在聚合之后进行过滤

Select name
from employee 
group by name
having sum(salary) > 1000 ;

【讨论】:

我只是想验证我为什么不能在 where 子句中使用聚合函数的解释。【参考方案4】:

使用有工作,因为查询直接到该列中的行,而 where 失败,因为只要不满足条件,查询就会不断来回循环。

【讨论】:

以上是关于SQL中的WHERE子句中为啥不允许应用聚集函数呢?请通俗的解释一下或者谈谈自己的见解!的主要内容,如果未能解决你的问题,请参考以下文章

SQL——聚集函数

SQL中WHERE 和HAVING的区别

在SQL语句中同时包含where子句,groupby子句,having子句及聚集函数,将按照怎么样的顺序执行?

为啥聚合函数不能放在where后面?

为啥不能再where语句中直接使用聚合函数

在oracle中where 子句和having子句中的区别