web-dev-qa-db-fra.com

L'utilisation de l'alias de colonne dans une clause WHERE ne fonctionne pas

Soit une table users avec deux champs: id et email.

select id, email as electronic_mail 
from (  
        select id, email 
        from users
) t 
where electronic_mail = ''

Postgres se plaint que:

ERROR:  column "electronic_mail" does not exist

L'exemple est juste pour démontrer le problème qui se pose. Mon cas réel est plus complexe, j'itère un tableau d'éléments dans une colonne json, en prenant une valeur scalaire unique pour chacun. (Je peux partager du code si cela aide.)

Je ne comprends vraiment pas ce que serait la complication, probablement je ne suis pas au courant de quelque chose. J'avais l'impression que les colonnes aliasées peuvent être utilisées dans une clause WHERE sans problème?

9
Victor

Le manuel clarifie ici:

Le nom d'une colonne de sortie peut être utilisé pour faire référence à la valeur de la colonne dans ORDER BY et GROUP BY clauses, mais pas dans les clauses WHERE ou HAVING; là, vous devez écrire l'expression à la place.

C'est selon la norme SQL et peut ne pas être très intuitif. La raison (historique) derrière cela est la séquence d'événements dans une requête SELECT. WHERE et HAVING sont résolus avant que les alias de colonne soient pris en compte, tandis que GROUP BY et ORDER BY se produit plus tard, après l'application des alias de colonne.
Notez également que les conflits entre les noms d'entrée et de sortie sont résolus différemment dans ORDER BY et GROUP BY - une autre bizarrerie historique (avec une raison derrière, mais potentiellement déroutante néanmoins). Voir:

Il est préférable d'éviter les alias de colonne qui entrent en conflit avec les noms de colonne d'entrée a priori.

En plus: la sous-requête dans votre exemple est juste du bruit puisque la clause WHERE fait partie de la requête externe, donc l'exemple peut être simplifié pour:

select id, email as electronic_mail 
from users t 
where electronic_mail = '';  -- doesn't work
13
Erwin Brandstetter