2009-06-03 2 views
144

Запрос я бегу следующим образом, однако я получаю эту ошибку:Используя псевдоним столбца в ИНЕКЕ запроса MySQL выдает ошибку

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

Мой вопрос: почему я не удалось использовать поддельный столбец в предложении where того же запроса БД?

ответ

334

Вы можете использовать только псевдонимы столбцов в предложениях GROUP BY, ORDER BY или HAVING.

Standard SQL doesn't allow you to refer to a column alias in a WHERE clause. This restriction is imposed because when the WHERE code is executed, the column value may not yet be determined.

Скопировано из MySQL documentation

Как указано в комментариях, используя HAVING вместо этого может делать свою работу. Обязательно прочитайте этот файл WHERE vs HAVING.

+11

+1 для ссылки (и точности) –

+1

Приветствия за быстрый и точный ответ! Я просмотрел предложение HAVING и разработал способ успешного выполнения этого запроса. Еще раз спасибо. – James

+26

В случае, если у кого-то еще такая же проблема, как у меня, которая использовала псевдонимы col в аргументе where, который не срабатывал, - заменив «WHERE» на «HAVING» сразу установил +1 хороший ответ. – megaSteve4

22

Как указал Виктор, проблема связана с псевдонимом. Этого можно избежать, хотя, помещая выражение непосредственно в пункте, где Х в У:

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

Однако, я полагаю, что это очень неэффективно, так как подчиненный запрос должен быть выполнен для каждой строки внешнего запроса.

+1

@rodion, Да, я считаю, что это ** сильно ** медленно и неэффективно. – Pacerier

17

Стандартный SQL (или баз данных) не допускает использование псевдонимов столбцов в предложении WHERE, потому что

when the WHERE clause is evaluated, the column value may not yet have been determined.

(от MySQL documentation). Вы можете вычислить значение столбца в разделе WHERE, сохранить значение в переменной и использовать его в списке полей. Например, вы можете сделать это:

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

Это позволяет избежать повторений выражения, когда он растет сложнее, делая проще код для сохранения.

+5

Не конфликтует ли с документацией [которая говорит] (http://stackoverflow.com/questions/16715504/mysql-define-a-variable-within-select-and-use-it-within-the-same- select/16715618 # 16715618) * «Как правило, вы никогда не должны присваивать значение переменной пользователя и читать значение в пределах одного и того же оператора. Вы можете получить ожидаемые результаты, но это не гарантируется». *? – Arjan

+0

Это определенно нужно иметь в виду. Это всегда срабатывало для меня, я думаю, что порядок оценки различных частей отчета должен был быть исправлен (сначала WHERE, затем SELECT, затем GROUP BY, ...), но у меня нет ссылки для этого – Joni

+0

Несколько примеров: некоторые [претензии] (http://stackoverflow.com/questions/16715504/mysql-define-a-variable-within-select-and-use-it-within-same-select/24551337# 24551337), что для них 'select @code: = sum (2), 2 * @ code' работает в MySQL 5.5, но для меня в 5.6 второй столбец дает NULL при первом вызове и возвращает 2 раза * предыдущий результат *, когда снова запустите. Интересно, что оба варианта: @code: = 2, 2 * @ code' и 'select @code: = rand(), 2 * @ code', похоже, работают в моем 5.6 (сегодня). Но они действительно записывают и читают в предложении SELECT; в вашем случае вы устанавливаете его в ГДЕ. – Arjan

1

Я использую MySQL 5.5.24 и следующий код работает:

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

Может быть, мой ответ будет слишком поздно, но это может помочь другим.

Вы можете заключить его в другой оператор select и использовать в нем предложение where.

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

calcAlias ​​- это столбец псевдонима, который был рассчитан.

+0

Приятный и короткий, но это слишком неопределенно, чтобы быть полезным. – Agamemnus

+0

@Agamemnus, Что вы подразумеваете под этим? – Pacerier

+0

Вопрос был: «Почему я не могу использовать поддельный столбец в предложении where того же запроса БД?» Этот ответ не отвечает на этот вопрос и не хватает глагола. – Agamemnus

7

Вы можете использовать HAVING условие для фильтра, рассчитанного в определенных областях и псевдонимы

+0

Я только что нашел Америку через год после вас. Кредит принадлежит вам: D –

+0

@ fahimg23 - Не уверен. Я пытался найти причину, но не могу! Однако имейте в виду различия между «WHERE» и «HAVING». Они не идентичны. https://stackoverflow.com/search?q=where+vs+having – rinogo

+0

UPDATE: Это потому, что [этот ответ] (https://stackoverflow.com/a/942592/114558) предоставляет такое же решение, но с дополнительной информацией. – rinogo

0

Стандартный SQL запрещает ссылки на псевдонимы столбцов в ИНЕКЕ. Это ограничение наложено, потому что, когда вычисляется предложение WHERE, значение столбца может еще не определено. Например, следующий запрос является незаконным:

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