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?
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.
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.
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 où 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.
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.
vous pouvez utiliser la clause avoir 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'
)
)
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;
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'
)
)