L’utilisation de l’alias de colonne dans la clause WHERE de la requête MySQL génère une erreur

La requête que je lance est la suivante, mais je reçois cette erreur:

# 1054 – Colonne inconnue’code_post garanti ‘dans’ IN / ALL / ANY sous-requête ‘

SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`, SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode` FROM `users` LEFT OUTER JOIN `locations` ON `users`.`id` = `locations`.`user_id` WHERE `guaranteed_postcode` NOT IN #this is where the fake col is being used ( SELECT `postcode` FROM `postcodes` WHERE `region` IN ( 'australia' ) ) 

Ma question est la suivante: pourquoi ne puis-je pas utiliser une fausse colonne dans la clause where de la même requête DB?

Vous ne pouvez utiliser que des alias de colonne dans les clauses GROUP BY, ORDER BY ou HAVING.

Le SQL standard ne vous permet pas de faire référence à un alias de colonne dans une clause WHERE. Cette ressortingction est imposée car lorsque le code WHERE est exécuté, la valeur de la colonne peut ne pas encore être déterminée.

Copié à partir de la documentation MySQL

Comme indiqué dans les commentaires, utiliser HAVING à la place peut faire le travail. Assurez-vous de donner une lecture à cet endroit par contre .

Comme Victor l’a fait remarquer, le problème vient de l’alias. Cela peut cependant être évité en plaçant directement l’expression dans la clause WHERE x IN:

 SELECT `users`.`first_name`,`users`.`last_name`,`users`.`email`,SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode` FROM `users` LEFT OUTER JOIN `locations` ON `users`.`id` = `locations`.`user_id` WHERE SUBSTRING(`locations`.`raw`,-6,4) NOT IN #this is where the fake col is being used ( SELECT `postcode` FROM `postcodes` WHERE `region` IN ( 'australia' ) ) 

Cependant, je suppose que cela est très inefficace, car la sous-requête doit être exécutée pour chaque ligne de la requête externe.

Le SQL standard (ou MySQL) n’autorise pas l’utilisation d’alias de colonnes dans une clause WHERE car

Lorsque la clause WHERE est évaluée, la valeur de la colonne n’a peut-être pas encore été déterminée.

(à partir de la documentation MySQL ). Ce que vous pouvez faire, c’est calculer la valeur de la colonne dans la clause WHERE , enregistrer la valeur dans une variable et l’utiliser dans la liste des champs. Par exemple, vous pouvez faire ceci:

 SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`, @postcode AS `guaranteed_postcode` FROM `users` LEFT OUTER JOIN `locations` ON `users`.`id` = `locations`.`user_id` WHERE (@postcode := SUBSTRING(`locations`.`raw`,-6,4)) NOT IN ( SELECT `postcode` FROM `postcodes` WHERE `region` IN ( 'australia' ) ) 

Cela évite de répéter l’expression lorsqu’elle devient compliquée, ce qui facilite la maintenance du code.

Peut-être que ma réponse est trop tard mais cela peut aider les autres.

Vous pouvez le joindre à une autre instruction select et utiliser la clause where.

 SELECT * FROM (Select col1, col2,...) as t WHERE t.calcAlias > 0 

calcAlias ​​est la colonne d’alias calculée.

Vous pouvez utiliser la clause HAVING pour le filtre calculé dans les champs SELECT et les alias

J’utilise mysql 5.5.24 et le code suivant fonctionne:

 select * from ( SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`, SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode` FROM `users` LEFT OUTER JOIN `locations` ON `users`.`id` = `locations`.`user_id` ) as a WHERE guaranteed_postcode NOT IN --this is where the fake col is being used ( SELECT `postcode` FROM `postcodes` WHERE `region` IN ( 'australia' ) ) 

Le SQL standard interdit les références aux alias de colonne dans une clause WHERE. Cette ressortingction est imposée car lorsque la clause WHERE est évaluée, la valeur de la colonne n’a peut-être pas encore été déterminée. Par exemple, la requête suivante est illégale:

SELECT ID, COUNT (*) AS cnt FROM nom_de_table WHERE cnt> 0 GROUP BY id;

Vous pouvez utiliser SUBSTRING ( locations . raw , -6,4) pour savoir où conditon

 SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`, SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode` FROM `users` LEFT OUTER JOIN `locations` ON `users`.`id` = `locations`.`user_id` WHERE SUBSTRING(`locations`.`raw`,-6,4) NOT IN #this is where the fake col is being used ( SELECT `postcode` FROM `postcodes` WHERE `region` IN ( 'australia' ) )