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

Nis*_*ngh 13 sql oracle aggregate-functions

我正在寻求对此的澄清.我在下面写两个问题:

我们有一个员工姓名表,列ID,姓名,薪水

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

  2.  Select name from employee 
    where substring_index(name,' ',1) = 'nishant' ;
Run Code Online (Sandbox Code Playgroud)

查询1不起作用,但查询2确实有效.根据我的开发经验,我觉得可能的解释是:

sum()适用于参数中指定的一组值.这里'salary'列被传递,因此它必须将此列的所有值相加.但是在where子句中,记录是逐个检查的,就像检查第一个记录1一样,等等.因此,sum(salary)将不会被计算,因为它需要访问所有列值,然后只返回一个值.

查询2作为substring_index()工作在单个值上,因此它在提供给它的值上工作.

你能否证实我的理解.

mat*_*guy 43

您不能SUM()WHERE条款中使用的原因是条款的评估顺序.

FROM告诉你从哪里读取行.正确地将行从磁盘读取到内存,然后检查它们的WHERE条件.(实际上在很多情况下,WHERE甚至无法从磁盘读取未通过该子句的行."条件"正式称为谓词,并且查询执行引擎使用一些谓词来决定从基表中​​读取哪些行.被称为访问谓词.)如您所见,该WHERE子句应用于每个行,因为它被呈现给引擎.

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

想一想:SUM()仅适用于满足WHERE条件的行.如果你SUM()加入WHERE条款,你就要求循环逻辑.新行是否通过了该WHERE条款?我怎么会知道?如果它会通过,那么我必须把它包括在内SUM,但如果没有,它就不应该包括在内SUM.那么我怎么评估SUM病情呢?

  • 如果您正在寻找解决方案,您所需要做的就是将“WHERE”语句移至“HAVING”子句中。 (2认同)
  • @deed02392 - 如果您在三年半后跳入,也许您应该阅读这个问题,直到您首先理解它。OP想要理解为什么条件**必须**位于“HAVING”子句中而不是位于“WHERE”子句中的理论原因。解决方案(与您提出的相同)很容易给出并且众所周知。更微妙的问题是**为什么**只能这样做。您可能还想阅读OP问题下的评论,其中进一步澄清了该线程的目的。 (2认同)

Gur*_*ngh 11

为什么我们可以在where子句中使用聚合函数

聚合函数适用于数据集.一个WHERE条款没有获得一整套,但仅限于该行,它目前正在对.

你当然可以使用HAVING子句:

select name from employee 
group by name having sum(salary) > 1000;
Run Code Online (Sandbox Code Playgroud)

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

select name from (
    select name, sum(salary) total_salary from employee
    group by name
) t where total_salary > 1000;
Run Code Online (Sandbox Code Playgroud)


Gor*_*off 6

sum()是一个聚合函数。通常,您希望它与group by. 因此,您的第一个查询缺少group by. 在group by查询中,having用于聚合的过滤:

Select name
from employee 
group by name
having sum(salary) > 1000 ;
Run Code Online (Sandbox Code Playgroud)