web-dev-qa-db-fra.com

Pourquoi les fonctions d'agrégation ne sont-elles pas autorisées dans la clause where

Je cherche des éclaircissements à ce sujet. J'écris deux requêtes ci-dessous:

Nous avons une table de nom d'employé avec les colonnes ID, nom, salaire

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

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

La requête 1 ne fonctionne pas mais la requête 2 fonctionne. D'après mon expérience de développement, je pense que l'explication possible est la suivante:

La somme () fonctionne sur un ensemble de valeurs spécifiées dans l'argument. Ici, la colonne "salaire" est passée, elle doit donc additionner toutes les valeurs de cette colonne. Mais à l'intérieur de la clause where, les enregistrements sont vérifiés un par un, comme le premier enregistrement 1 est vérifié pour le test et ainsi de suite. Ainsi, sum (salaire) ne sera pas calculé car il a besoin d'accéder à toutes les valeurs de colonne et alors seulement il renverra une valeur.

La requête 2 fonctionne comme substring_index () fonctionne sur une seule valeur et donc ici, elle fonctionne sur la valeur qui lui est fournie.

Pouvez-vous s'il vous plaît valider ma compréhension.

13
Nishant_Singh

La raison pour laquelle vous ne pouvez pas utiliser SUM() dans la clause WHERE est l'ordre d'évaluation des clauses.

FROM vous indique où lire les lignes. Dès que les lignes sont lues du disque dans la mémoire, les conditions WHERE sont vérifiées. (En fait, dans de nombreux cas, les lignes qui échouent à la clause WHERE ne seront même pas lues à partir du disque. Les "conditions" sont officiellement appelées prédicats et certains prédicats sont utilisés - par le moteur d'exécution de la requête - pour décider quelles lignes sont lues à partir des tables de base. Celles-ci sont appelées prédicats access.) Comme vous pouvez le voir, la clause WHERE est appliquée à chaque ligne telle qu'elle est présentée au moteur.

En revanche, l'agrégation n'est effectuée qu'après la lecture de toutes les lignes (qui vérifient tous les prédicats).

Réfléchissez à ceci: SUM() s'applique UNIQUEMENT aux lignes qui remplissent les conditions WHERE. Si vous mettez SUM() dans la clause WHERE, vous demandez une logique circulaire. Une nouvelle ligne passe-t-elle la clause WHERE? Comment pourrais-je savoir? S'il passe, alors je dois l'inclure dans le SUM, mais sinon, il ne devrait pas être inclus dans le SUM. Alors, comment puis-je même évaluer la condition SUM?

39
mathguy

Pourquoi pouvons-nous utiliser la fonction d'agrégation dans la clause where

Les fonctions d'agrégation fonctionnent sur des ensembles de données. Une clause WHERE n'a pas accès à l'ensemble complet, mais uniquement à la ligne sur laquelle elle travaille actuellement.

Vous pouvez bien sûr utiliser la clause HAVING:

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

Si vous devez utiliser WHERE, vous pouvez utiliser une sous-requête:

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

sum() est une fonction d'agrégation. En général, vous vous attendez à ce qu'il fonctionne avec group by. Par conséquent, il manque à votre première requête un group by. Dans un group by requête, having est utilisé pour filtrer après l'agrégation:

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