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
子句 - 将所有行放在一个组)。正如我解释的那样,原因是这需要循环推理,因为 max
和 avg
并未应用于基表中的所有行;它们仅应用于满足 @987654332 的行@ 条件!如果整个基表需要max
或avg
,则必须在子查询中单独计算。
【参考方案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子句中为啥不允许应用聚集函数呢?请通俗的解释一下或者谈谈自己的见解!的主要内容,如果未能解决你的问题,请参考以下文章