web-dev-qa-db-fra.com

Pourquoi ne puis-je pas exécuter une fonction d'agrégation sur une expression contenant un agrégat mais je peux le faire en créant une nouvelle instruction select autour d'elle?

Pourquoi est-ce que dans SQL Server je ne peux pas faire ça:

select  sum(count(id)) as 'count'
from    table

Mais je peux faire

select sum(x.count)
from
(
    select  count(id) as 'count'
    from    table   
) x

N'est-ce pas essentiellement la même chose? Comment dois-je penser à cela pour comprendre pourquoi le premier bloc de code n'est pas autorisé?

27
Michael A

SUM () dans votre exemple est un no-op - SUM () d'un COUNT () signifie la même chose que COUNT (). Ainsi, aucune de vos requêtes d'exemple ne semble faire quoi que ce soit d'utile.

Il me semble que l'imbrication d'agrégats n'aurait de sens que si vous vouliez appliquer deux agrégations différentes - c'est-à-dire GROUP BY sur différents ensembles de colonnes. Pour spécifier deux agrégations différentes, vous devez utiliser la fonction GROUPING SETS ou SUM () OVER. Peut-être que si vous expliquez ce que vous voulez réaliser, quelqu'un pourrait vous montrer comment.

14
nvogel

L'essentiel de la question est qu'il n'y a pas de concept d'agrégat d'un agrégat appliqué à une relation, voir Agrégation . Avoir un tel concept laisserait trop de trous dans la définition et rendrait la clause GROUP BY impossible à exprimer: il faut définir à la fois la clause GROUP BY agrégée interne et l'agrégat extérieur aussi! Cela s'applique également aux autres attributs agrégés, comme la clause HAVING.

Cependant, le résultat d'un agrégat appliqué à une relation est une autre relation, et cette relation de résultat à son tour peut prendre en charge un nouvel opérateur d'agrégat. Cela explique pourquoi vous pouvez agréger le résultat dans un SELECT externe. Cela ne laisse aucune ambiguïté dans la définition, chaque SELECT a ses propres clauses GROUP BY/HAVING distinctes.

8
Remus Rusanu

En termes simples, les fonctions d'agrégation fonctionnent sur une colonne et génèrent une valeur scalaire, elles ne peuvent donc pas être appliquées à leur résultat. Lorsque vous créez une instruction select sur une valeur scalaire, vous la transformez en une colonne artificielle, c'est pourquoi elle peut à nouveau être utilisée par une fonction d'agrégation.

Veuillez noter que la plupart du temps, il est inutile d'appliquer une fonction d'agrégation sur le résultat d'une autre fonction d'agrégation: dans votre exemple sum(count(id)) == count(id).

1
Gerardo Lima

je voudrais savoir quel est votre résultat attendu dans ce sql

select  sum(count(id)) as 'count'
from    table

lorsque vous utilisez la fonction count, seul 1 résultat (nombre total) sera renvoyé. Alors, puis-je vous demander pourquoi vous voulez additionner le seul 1 résultat.

Vous obtiendrez sûrement l'erreur car une fonction d'agrégation ne peut pas fonctionner sur une expression contenant un agrégat ou une sous-requête.

1
AKZap

Cela fonctionne pour moi en utilisant SQLFiddle , je ne sais pas pourquoi cela ne fonctionnerait pas pour vous. Mais j'ai une explication pour expliquer pourquoi cela pourrait ne pas fonctionner pour vous et pourquoi l'alternative fonctionnerait ...

Votre exemple utilise un mot clé comme nom de colonne, qui peut ne pas toujours fonctionner. Mais lorsque la colonne est uniquement dans une sous-expression, le moteur de requête est libre de supprimer le nom (en fait, il le fait probablement), de sorte que le fait qu'il puisse potentiellement entrer en conflit avec un mot clé peut être ignoré.

EDIT: en réponse à votre édition/commentaire. Non, les deux ne sont pas équivalents. Le RÉSULTAT serait équivalent, mais le processus pour arriver à ce résultat n'est pas du tout similaire. Pour que le premier fonctionne, l'analyseur a effectué un travail qui n'a tout simplement pas de sens pour lui (appliquer un agrégat à une seule valeur, soit ligne par ligne ou en tant que), dans le second cas, un agrégat est appliqué à une table. Le fait que la table soit une table virtuelle temporaire sera sans importance pour la fonction d'agrégation.

1
jmoreno