Juste curieux de connaître la syntaxe SQL. Donc si j'ai
SELECT
itemName as ItemName,
substring(itemName, 1,1) as FirstLetter,
Count(itemName)
FROM table1
GROUP BY itemName, FirstLetter
Ce serait incorrect parce que
GROUP BY itemName, FirstLetter
devrait vraiment être
GROUP BY itemName, substring(itemName, 1,1)
Mais pourquoi ne pouvons-nous pas simplement utiliser l'ancien pour plus de commodité?
SQL est implémenté comme si une requête était exécutée dans l'ordre suivant:
Pour la plupart des systèmes de bases de données relationnelles, cet ordre explique quels noms (colonnes ou alias) sont valides, car ils doivent avoir été introduits à une étape précédente.
Ainsi, dans Oracle et SQL Server, vous ne pouvez pas utiliser un terme dans la clause GROUP BY que vous définissez dans la clause SELECT, car GROUP BY est exécuté avant la clause SELECT.
Il existe cependant des exceptions: MySQL et Postgres semblent avoir l’intelligence supplémentaire qui le permet.
Vous pouvez toujours utiliser une sous-requête pour pouvoir utiliser l'alias. Bien sûr, vérifiez les performances (il est possible que le serveur de base de données exécute les deux de la même manière, mais ne bloque jamais pour vérification):
SELECT ItemName, FirstLetter, COUNT(ItemName)
FROM (
SELECT ItemName, SUBSTRING(ItemName, 1, 1) AS FirstLetter
FROM table1
) ItemNames
GROUP BY ItemName, FirstLetter
Au moins dans PostgreSQL, vous pouvez utiliser le numéro de colonne dans le jeu de résultats de votre clause GROUP BY:
SELECT
itemName as ItemName,
substring(itemName, 1,1) as FirstLetter,
Count(itemName)
FROM table1
GROUP BY 1, 2
Bien sûr, cela commence à être un problème si vous le faites de manière interactive et que vous modifiez la requête pour modifier le nombre ou l'ordre des colonnes dans le résultat. Mais reste.
SQL Server ne vous permet pas de référencer l'alias dans la clause GROUP BY en raison de l'ordre logique du traitement. La clause GROUP BY étant traitée avant la clause SELECT, l'alias n'est pas connu lors de l'évaluation de la clause GROUP BY. Cela explique également pourquoi vous pouvez utiliser l'alias dans la clause ORDER BY.
Voici une source d’informations sur = phases de traitement logique de SQL Server .
Je ne réponds pas pourquoi, mais je voulais seulement montrer comment contourner cette limitation dans SQL Server en utilisant CROSS APPLY
pour créer l'alias. Vous l'utilisez ensuite dans le GROUP BY
clause, comme suit:
SELECT
itemName as ItemName,
FirstLetter,
Count(itemName)
FROM table1
CROSS APPLY (SELECT substring(itemName, 1,1) as FirstLetter) Alias
GROUP BY itemName, FirstLetter
Attention, l'utilisation d'alias dans Group By (pour les services qui le prennent en charge, tels que postgres) peut avoir des résultats inattendus. Par exemple, si vous créez un alias qui existe déjà dans l'instruction interne, le groupe par choisira le nom du champ interne.
-- Working example in postgres
select col1 as col1_1, avg(col3) as col2_1
from
(select gender as col1, maritalstatus as col2,
yearlyincome as col3 from customer) as layer_1
group by col1_1;
-- Failing example in postgres
select col2 as col1, avg(col3)
from
(select gender as col1, maritalstatus as col2,
yearlyincome as col3 from customer) as layer_1
group by col1;
Certains SGBD vous permettent d'utiliser un alias au lieu de devoir répéter toute l'expression.
Teradata en est un exemple.
J'évite la notation de position ordinale recommandée par Bill pour des raisons documentées dans this SO question .
L’alternative simple et robuste consiste à toujours répéter l’expression dans la clause GROUP BY.
DRY NE s'applique PAS à SQL.
Attention aux alias lors du regroupement des résultats d'une vue dans SQLite. Vous obtiendrez des résultats inattendus si le nom d'alias est identique au nom de colonne de toutes les tables sous-jacentes (aux vues).
À l'époque, j'ai découvert que Rdb, l'ancien produit DEC maintenant pris en charge par Oracle, permettait à l'alias de colonne d'être utilisé dans GROUP BY. Mainstream Oracle jusqu’à la version 11 ne permet pas l’utilisation de l’alias de colonne dans GROUP BY. Je ne sais pas ce que Postgresql, SQL Server, MySQL, etc. permettront ou ne permettront pas. YMMV.