web-dev-qa-db-fra.com

Pourquoi Oracle SQL ne nous autorise-t-il pas à utiliser des alias de colonne dans les clauses GROUP BY?

C'est une situation à laquelle je suis généralement confronté lors de l'écriture de requêtes SQL. Je pense que l'écriture de la colonne entière (par exemple, les expressions de casse longues, les fonctions de somme avec des paramètres longs) au lieu des alias dans les expressions GROUP BY rend la requête plus longue et moins lisible. Pourquoi Oracle SQL ne nous autorise-t-il pas à utiliser les alias de colonne dans la clause GROUP BY? Il doit y avoir une raison importante derrière cela.

26

Ce n'est pas seulement Oracle SQL, en fait je pense qu'il est conforme à la norme ANSI SQL (bien que je n'ai pas de référence pour cela). La raison en est que la clause SELECT est traitée logiquement après la clause GROUP BY, donc au moment où le GROUP BY est terminé, les alias n'existent pas encore.

Peut-être que cet exemple quelque peu ridicule aide à clarifier le problème et l'ambiguïté que SQL évite:

SQL> select job as sal, sum(sal) as job
  2  from scott.emp
  3  group by job;

SAL              JOB
--------- ----------
ANALYST         6000
CLERK           4150
MANAGER         8275
PRESIDENT       5000
SALESMAN        5600
45
Tony Andrews

Je sais que c'est un vieux fil, mais il semble que le problème des utilisateurs n'ait pas été vraiment résolu; les explications étaient bonnes pour expliquer pourquoi la clause group by ne vous permet pas d'utiliser des alias, mais aucune alternative n'a été donnée.

Sur la base des informations ci-dessus, les alias ne peuvent pas être utilisés dans le groupe par car le groupe par s'exécute en premier, avant que les alias de la clause select soient stockés en mémoire. Donc, la solution simple qui a fonctionné pour moi était d'ajouter une sélection externe qui sélectionne simplement les alias, puis les regroupe à ce même niveau.

Exemple:

SELECT alias1, alias2, alias3, aliasN
FROM
(SELECT field1 as alias1, field2 as alias2, field3 as alias3, fieldN as aliasN
 FROM tableName
 WHERE ' ' = ' ')
GROUP BY alias1, alias2, alias3, aliasN

Assez simple une fois que vous voyez la solution, mais un PITA si vous essayez de comprendre par vous-même pour la première fois.

C'est la seule façon dont j'ai pu "grouper" pour un champ dérivé d'une déclaration de cas, c'est donc une bonne astuce à savoir.

13
keith

Bien que cela semble une réponse logique, en fait, elle est très peu conviviale. Avant de traiter la requête, Oracle la lit et, en la lisant, le préprocesseur peut remplacer l'alias par l'instruction d'origine et toujours envoyer la requête correcte à la base de données. de la même façon que vous pouvez coder l'ordre par 1,2,3, vous devriez également pouvoir grouper par 1,2,3 ou alias.

3
Tom Heitbrink

Bien que je convienne qu'il serait utile de référencer des expressions avec des alias dans la clause GROUP BY, je suppose que ce n'est pas possible car la clause GROUP BY est évaluée avant la clause SELECT.

Cela expliquerait également pourquoi vous pouvez utiliser des alias de colonne dans la clause ORDER BY (i-e: la clause ORDER BY est évaluée en dernier).

3
Vincent Malgrat

Mais certains RDBMS le font, cela fonctionne sur PostgreSQL:

select emp.lastname || ' ' || emp.firstname as fullname, count(emp_work.*) as cnt
from emp
left join emp_work using(emp_id)
group by fullname

Cela fonctionnera, tant que l'alias groupé n'est pas le résultat de fonctions d'agrégation, group by cnt ne fonctionnera pas

Mais je peux hasarder une supposition que group by fullname est étendu à group by emp.lastname || ' ' || emp.firstname as fullname, et la clause SELECT sélectionne simplement le résultat du nom complet de ce regroupement; bien que syntaxiquement, il regarde dans l'autre sens. GROUP s'exécute toujours en premier, puis les projections en dernier (c'est-à-dire SELECT)

2
Michael Buen