Utilisation de l'alias de la colonne dans laquelle la clause de la requête MySQL produit une erreur

la requête que j'exécute est la suivante, cependant j'obtiens cette erreur:

#1054 - Unknown column 'guaraned_postcode' in 'IN/ALL/ANY subquery'

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: pourquoi suis-je incapable d'utiliser une fausse colonne dans la clause où de la même requête DB?

157
demandé sur OMG Ponies 2009-06-03 04:31:58

8 réponses

vous ne pouvez utiliser les alias de colonne dans le groupe par, ordre par, ou ayant des clauses.

SQL Standard ne vous permet pas de référez-vous à une colonne alias dans un WHERE clause. Cette restriction est imposée parce que quand le code où est exécuté, la valeur de la colonne peut pas encore être déterminé.

copié de documentation MySQL

comme indiqué dans les observations, en utilisant au lieu de cela peut faire le travail. Assurez-vous de donner une lecture à ce où vs ayant cependant.

362
répondu victor hugo 2018-09-25 18:06:56

comme Victor l'a souligné, le problème est avec l'alias. Cela peut être évité, cependant, en mettant l'expression directement dans la clause où x Dans y:

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 c'est très inefficace, puisque la sous-requête doit être exécuté pour chaque ligne de la requête externe.

23
répondu rodion 2009-06-03 00:47:09

standard SQL (ou MySQL) ne permet pas l'utilisation d'alias de colonne dans une clause WHERE parce que

lorsque la clause WHERE est évaluée, la valeur de la colonne peut ne pas avoir encore été déterminée.

(de documentation de MySQL ). Ce que vous pouvez faire est de calculer la valeur de la colonne dans la clause, enregistrer la valeur dans une variable, et de l'utiliser dans la liste des champs. Exemple vous pourriez 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 quand elle devient compliquée, ce qui rend le code plus facile à maintenir.

17
répondu Joni 2017-07-20 05:30:27

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

vous pouvez l'inclure avec une autre instruction select et utiliser la clause where pour elle.

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

calcAlias est la colonne alias qui a été calculée.

11
répondu George Khouri 2014-08-29 13:03:31

vous pouvez utiliser la clause avoir pour le filtre calculé dans les champs SELECT et les alias

7
répondu Hett 2016-02-15 07:35:12

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'
 )
)
1
répondu themis 2016-11-09 03:13:02

Standard SQL n'autorise pas de références à des alias de colonne dans une clause where. Cette restriction est imposée parce que 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:

sélectionner id, COUNT (*) comme cnt à partir de tbl_name où cnt > 0 GROUP par id;

0
répondu Pavan Rajput 2016-09-27 05:28:31

vous pouvez utiliser le substrat ( locations . raw , -6,4) pour laquelle 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'
)
)
0
répondu Sameera Prasad Jayasinghe 2018-03-21 10:02:21