Неизвестный столбец в предложении Where


126

У меня простой запрос:

SELECT u_name AS user_name FROM users WHERE user_name = "john";

Я понимаю Unknown Column 'user_name' in where clause. Могу ли я не ссылаться на 'user_name'другие части заявления даже после select 'u_name as user_name'?

Ответы:


94

SQL оценивается в обратном порядке, справа налево. Таким образом, предложение where анализируется и оценивается до предложения select. Из-за этого псевдоним u_name на user_name еще не произошел.


30
Я думаю, что будет больше смысла сказать «наизнанку», чем «назад»
Джо Филлипс

4
Более логично сказать, что весь оператор анализируется, преобразуется и оптимизируется в целом в рамках сложного многоступенчатого процесса. «SQL оценивается в обратном порядке, справа налево» просто неправильно
Дэвид Олдридж

3
неполный ответ, поскольку пользователь спросил, можно ли использовать "user_name" в заявлении, что может быть после, например, "HAVING"
luke_mclachlan

45

Что о:

SELECT u_name AS user_name FROM users HAVING user_name = "john";

16
Почему бы вы использовали HAVINGвместо этого WHEREв этом случае?
PeteGO

4
@PeteGO относится к ответу Пола Диксона. tldr; HAVING оценивается позже, чем WHERE и, что более важно, SELECT.
jairbow

38

См. Следующую страницу руководства MySQL: http://dev.mysql.com/doc/refman/5.0/en/select.html

«Выражению select_expr можно присвоить псевдоним с помощью AS alias_name. Псевдоним используется как имя столбца выражения и может использоваться в предложениях GROUP BY, ORDER BY или HAVING».

(...)

Недопустимо ссылаться на псевдоним столбца в предложении WHERE, потому что значение столбца может еще не быть определено при выполнении предложения WHERE. См. Раздел B.5.4.4, «Проблемы с псевдонимами столбцов».


Также обратите внимание (от человека по MySQL): стандарт SQL требует, чтобы HAVING ссылался только на столбцы в предложении GROUP BY или столбцы, используемые в агрегатных функциях. Однако MySQL поддерживает расширение этого поведения и позволяет HAVING ссылаться на столбцы в списке SELECT, а также на столбцы во внешних подзапросах.
Винсент Пазеллер,

12
select u_name as user_name from users where u_name = "john";

Подумайте об этом так: ваше предложение where сначала оценивается, чтобы определить, какие строки (или соединенные строки) необходимо вернуть. После выполнения предложения where для него выполняется предложение select.

Проще говоря, представьте себе следующее:

select distinct(u_name) as user_name from users where u_name = "john";

Вы не можете ссылаться на первую половину без второй. Где всегда сначала оценивается, затем предложение select.


11

Если вы пытаетесь выполнить следующий запрос (найти все узлы с хотя бы одним вложением), в котором вы использовали оператор SELECT для создания нового поля, которое на самом деле не существует в базе данных, и попробуйте использовать псевдоним для этого результата вы столкнетесь с той же проблемой:

SELECT nodes.*, (SELECT (COUNT(*) FROM attachments 
WHERE attachments.nodeid = nodes.id) AS attachmentcount 
FROM nodes
WHERE attachmentcount > 0;

Вы получите сообщение об ошибке «Неизвестный столбец 'attachmentcount' в предложении WHERE».

Решение на самом деле довольно простое - просто замените псевдоним оператором, который создает псевдоним, например:

SELECT nodes.*, (SELECT (COUNT(*) FROM attachments 
WHERE attachments.nodeid = nodes.id) AS attachmentcount 
FROM nodes 
WHERE (SELECT (COUNT(*) FROM attachments WHERE attachments.nodeid = nodes.id) > 0;

Вы все равно получите возвращенный псевдоним, но теперь SQL не должен работать с неизвестным псевдонимом.


1
Я столкнулся с этой проблемой и наткнулся на ваш ответ - спасибо! Следует отметить, что это (понятно) немного медленнее для больших баз данных, но я все равно имею дело с глупой настройкой унаследованной базы данных.
Лиам Ньюмарч

Я считаю, что (в вашем запросе есть лишнее, (COUNT(*)которое нигде не закрывается.
tftd

3
Но разве оператор SELECT не запускается дважды?
Matej

Я далеко не эксперт по mysql, но это кажется очень неэффективным. Я испытал, что вложенные выборки делают запрос намного медленнее.
GDY

8

Ваше определение aliasне приветствуется WHEREпредложением, которое вы должны использовать HAVINGдля этого

SELECT u_name AS user_name FROM users HAVING user_name = "john";

ИЛИ вы можете напрямую использовать исходное имя столбца с WHERE

SELECT u_name AS user_name FROM users WHERE u_name = "john";

Так же, как у вас есть результат в определяемом пользователем псевдониме в результате подзапроса или любого вычисления, к нему будет обращаться HAVINGпредложение, а неWHERE

SELECT u_name AS user_name ,
(SELECT last_name FROM users2 WHERE id=users.id) as user_last_name
FROM users  WHERE u_name = "john" HAVING user_last_name ='smith'

7

Либо:

SELECT u_name AS user_name
FROM   users
WHERE  u_name = "john";

или:

SELECT user_name
from
(
SELECT u_name AS user_name
FROM   users
)
WHERE  u_name = "john";

Последний должен быть таким же, как первый, если СУБД поддерживает отправку предикатов во встроенное представление.



5

Нет, вам нужно выбрать его с правильным именем. Если вы указали выбранную таблицу из псевдонима, вы можете использовать это.



1

Неизвестный столбец в WHEREпредложении, вызванный строками 1 и 2 и разрешенный строкой 3:

  1. $sql = "SELECT * FROM users WHERE username =".$userName;
  2. $sql = "SELECT * FROM users WHERE username =".$userName."";
  3. $sql = "SELECT * FROM users WHERE username ='".$userName."'";

Что вы изменили и почему? Кроме того, почему вы разместили код, который широко открыт для инъекций SQL?
Нико Хаасе

1

Может быть поможет.

Ты можешь

SET @somevar := '';
SELECT @somevar AS user_name FROM users WHERE (@somevar := `u_name`) = "john";

Оно работает.

НО УБЕДИТЕСЬ, ЧТО ВЫ ДЕЛАЕТЕ!

  • Индексы здесь НЕ ИСПОЛЬЗУЮТСЯ
  • Будет просканирована ПОЛНАЯ ТАБЛИЦА - вы не указали часть LIMIT 1
  • Итак, - ЭТОТ ЗАПРОС БУДЕТ ПРОСМОТРЕТЬ на огромных таблицах.

Но, может быть, в некоторых случаях это помогает


0

Хотя вы можете использовать псевдонимы для своих таблиц в запросе (например, «SELECT u.username FROM users u;»), вы должны использовать фактические имена столбцов, на которые вы ссылаетесь. AS влияет только на то, как возвращаются поля.


Я думаю, вы можете использовать псевдоним в некоторых СУБД, например MySql. Однако вы правы для Sql Server.
PeteGO

0
SELECT user_name
FROM
(
SELECT name AS user_name
FROM   users
) AS test
WHERE  user_name = "john"

Почему вы хотите использовать подзапрос? Гораздо проще без.
PeteGO

0

Просто была эта проблема.

Убедитесь, что в имени объекта в базе данных нет места.

например, user_name вместо user_name


-1

попробуйте свою задачу, используя условие IN или условие OR, а также этот запрос работает с spark-1.6.x

 SELECT  patient, patient_id FROM `patient` WHERE patient IN ('User4', 'User3');

или

SELECT  patient, patient_id FROM `patient` WHERE patient = 'User1' OR patient = 'User2';

-1

Для меня корнем проблемы был номер, который я скопировал для использования в предложении WHERE. У номера был «невидимый» символ, по крайней мере, для MySQL Workbench. Я поместил номер в консоль Chrome, он был хорошо виден.


-2

У меня была такая же проблема, я нашел это полезным.

mysql_query("SELECT * FROM `users` WHERE `user_name`='$user'");

не забудьте заключить $ user в одинарные кавычки.


1
Этот код широко открыт для внедрения SQL. Никто не должен использовать этот код для решения данной проблемы
Нико Хаасе
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.