El uso de alias de columna en la cláusula WHERE de la consulta MySQL produce un error


La consulta que estoy ejecutando es la siguiente, sin embargo, estoy recibiendo este error:

#1054-Unknown column 'guaranteed_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'
 )
)

Mi pregunta es: ¿por qué no puedo usar una columna falsa en la cláusula where de la misma consulta de BD?

Author: OMG Ponies, 2009-06-03

8 answers

Solo puede usar alias de columna en las cláusulas GROUP BY, ORDER BY o HAVING.

SQL estándar no le permite refiérase a un alias de columna en una DONDE clausula. Esta restricción se impone porque cuando el código DONDE está ejecutado, el valor de la columna aún no puede sé decidido.

Copiado de Documentación MySQL

Como se señala en los comentarios, usar TENER en su lugar puede hacer el trabajo. Asegúrese de dar una lectura en este DONDE vs TENER aunque.

 362
Author: victor hugo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-25 18:06:56

Como Victor señaló, el problema es con el alias. Sin embargo, esto se puede evitar poniendo la expresión directamente en la cláusula WHERE x IN 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'
 )
)

Sin embargo, supongo que esto es muy ineficiente, ya que la subconsulta tiene que ejecutarse para cada fila de la consulta externa.

 23
Author: rodion,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-03 00:47:09

SQL estándar (o MySQL) no permite el uso de alias de columna en una cláusula WHERE porque

Cuando se evalúa la cláusula WHERE, es posible que el valor de la columna aún no se haya determinado.

(de documentación MySQL ). Lo que puede hacer es calcular el valor de la columna en la cláusula WHERE, guardar el valor en una variable y usarlo en la lista de campos. Por ejemplo, usted podría hacer esto:

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'
 )
)

Esto evita repetir la expresión cuando se complica, haciendo que el código sea más fácil de mantener.

 17
Author: Joni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-20 05:30:27

Tal vez mi respuesta es demasiado tarde, pero esto puede ayudar a otros.

Puede encerrarlo con otra instrucción select y usar la cláusula where.

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

CalcAlias es la columna alias que se calculó.

 11
Author: George Khouri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-29 13:03:31

Puede usar la cláusula HAVING para el filtro calculado en SELECCIONAR campos y alias

 7
Author: Hett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-15 07:35:12

Estoy usando mysql 5.5.24 y el siguiente código funciona:

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
Author: themis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-09 03:13:02

SQL estándar no permite referencias a alias de columna en una cláusula WHERE. Esta restricción se impone porque cuando se evalúa la cláusula WHERE, es posible que el valor de la columna aún no se haya determinado. Por ejemplo, la siguiente consulta es ilegal:

SELECCIONE id, CUENTE(*) COMO cnt DESDE tbl_name DONDE cnt > 0 AGRUPA POR id;

 0
Author: Pavan Rajput,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-27 05:28:31

Puede usar SUBCADENA(locations.raw, -6,4) para donde 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
Author: Sameera Prasad Jayasinghe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-21 10:02:21