Pouvez-vous utiliser un alias dans la clause WHERE de mysql?

121

J'ai besoin d'utiliser un alias dans la clause WHERE, mais il ne cesse de me dire que c'est une colonne inconnue. Existe-t-il un moyen de contourner ce problème? Je dois sélectionner des enregistrements dont la note est supérieure à x. L'évaluation est calculée comme l'alias suivant:

sum(reviews.rev_rating)/count(reviews.rev_id) as avg_rating
dreftymac
la source

Réponses:

229

Vous pouvez utiliser une clause HAVING, qui peut voir les alias, par exemple

 HAVING avg_rating>5

mais dans une clause where, vous devrez répéter votre expression, par exemple

 WHERE (sum(reviews.rev_rating)/count(reviews.rev_id))>5

MAIS! Toutes les expressions ne seront pas autorisées - l'utilisation d'une fonction d'agrégation comme SUM ne fonctionnera pas, auquel cas vous devrez utiliser une clause HAVING.

À partir du manuel MySQL :

Il n'est pas permis de faire référence à un alias de colonne dans une clause WHERE, car la valeur de la colonne peut ne pas encore être déterminée lorsque la clause WHERE est exécutée. Voir Section B.1.5.4, «Problèmes avec les alias de colonne» .

Paul Dixon
la source
1
Si je répète l'expression, cela me dit: "utilisation non valide de la fonction de groupe"
3
Ont reformulé pour rendre plus clair les fonctions d'agrégation non autoriséesd
Paul Dixon
Belle explication, en particulier. la partie "mais dans une clause where ... repeat .."
th3an0maly
4
C'est une bonne réponse, mais veuillez considérer les implications sur les performances car HAVINGs'exécute après la récupération des données et WHEREs'exécute avant.
StockB
Vous ne pouvez pas utiliser de fonctions d'agrégation dans une clause WHERE. La clause WHERE ne filtre que les lignes une à la fois, pas des groupes entiers.
Bill Karwin
33

Je ne sais pas si cela fonctionne dans mysql mais en utilisant sqlserver, vous pouvez également simplement l'envelopper comme:

select * from (
  -- your original query
  select .. sum(reviews.rev_rating)/count(reviews.rev_id) as avg_rating 
  from ...) Foo
where Foo.avg_rating ...
Torbjörn Gyllebring
la source
6

Cette question est assez ancienne et une réponse a déjà recueilli 160 voix ...

Je voudrais néanmoins préciser ceci: la question n'est pas en fait de savoir si les noms d'alias peuvent être utilisés dans la WHEREclause.

sum(reviews.rev_rating) / count(reviews.rev_id) as avg_rating

est une agrégation. Dans la WHEREclause, nous restreignons les enregistrements que nous voulons des tables en examinant leurs valeurs. sum(reviews.rev_rating)et count(reviews.rev_id), cependant, ne sont pas des valeurs que nous trouvons dans un enregistrement; ce sont des valeurs que nous n'obtenons qu'après agrégation des enregistrements.

C'est donc WHEREinapproprié. Nous avons besoin HAVING, car nous voulons restreindre les lignes de résultats après agrégation. Ça ne peut pas être

WHERE avg_rating > 10

ni

WHERE sum(reviews.rev_rating) / count(reviews.rev_id) > 10

Par conséquent.

HAVING sum(reviews.rev_rating) / count(reviews.rev_id) > 10

d'autre part est possible et conforme à la norme SQL. Tandis que

HAVING avg_rating > 10

n'est possible que dans MySQL. Ce n'est pas du SQL valide selon la norme, car la SELECTclause est censée être exécutée après HAVING. À partir de la documentation MySQL:

Une autre extension MySQL du SQL standard autorise les références dans la clause HAVING à des expressions aliasées dans la liste de sélection.

L'extension MySQL permet l'utilisation d'un alias dans la clause HAVING pour la colonne agrégée

https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

Thorsten Kettner
la source
0

Si votre requête est statique, vous pouvez la définir comme une vue, puis vous pouvez utiliser cet alias dans la clause where lors de l'interrogation de la vue.

alpère
la source
0
SELECT * FROM (SELECT customer_Id AS 'custId', gender, age FROM customer
    WHERE  gender = 'F') AS c
WHERE c.custId = 100;
Anson
la source