条款中的未知栏目

111 mysql sql mysql-error-1054

我有一个简单的查询:

SELECT u_name AS user_name FROM users WHERE user_name = "john";
Run Code Online (Sandbox Code Playgroud)

我得到Unknown Column 'user_name' in where clause.'user_name'即使之后,我还不能在声明的其他部分提及select 'u_name as user_name'吗?

dac*_*cot 82

SQL从右到左向后评估.因此,在select子句之前解析和评估where子句.因此,尚未发生u_name到user_name的别名.

  • 而不是"倒退",我认为说"内向外"更有意义 (25认同)
  • 更有意义的是,整个语句在复杂的多阶段过程中作为一个整体进行解析,转换和优化."从右到左反向评估SQL"是错误的 (3认同)
  • 不完整的答案,因为用户询问是否可以在语句中使用“user_name”,它可以在例如“HAVING”之后 (3认同)
  • 不是从里到外,从右到左? (2认同)

小智 38

关于什么:

SELECT u_name AS user_name FROM users HAVING user_name = "john";
Run Code Online (Sandbox Code Playgroud)

  • 在这种情况下,为什么要使用`HAVING`而不是`WHERE`? (16认同)
  • @PeteGO参考了Paul Dixon的回答.tldr; HAVING的评估晚于WHERE,更重要的是SELECT. (3认同)

Pau*_*xon 35

请参阅以下MySQL手册页:http://dev.mysql.com/doc/refman/5.0/en/select.html

"可以使用AS alias_name为select_expr指定别名.别名用作表达式的列名,可以在GROUP BY,ORDER BY或HAVING子句中使用."

(......)

不允许在WHERE子句中引用列别名,因为在执行WHERE子句时可能尚未确定列值.请参见第B.5.4.4节"列别名的问题".


Mar*_* S. 12

select u_name as user_name from users where u_name = "john";
Run Code Online (Sandbox Code Playgroud)

可以这样想,你的where子句首先计算,以确定需要返回哪些行(或连接的行).执行where子句后,将为其运行select子句.

为了更好的方式,想象一下:

select distinct(u_name) as user_name from users where u_name = "john";
Run Code Online (Sandbox Code Playgroud)

没有第二个,你不能参考前半部分.总是首先评估的地方,然后是select子句.


小智 10

如果您尝试执行如下所示的查询(查找具有至少一个附件的所有节点),您使用SELECT语句创建一个实际上不存在于数据库中的新字段,并尝试使用该结果的别名你将遇到同样的问题:

SELECT nodes.*, (SELECT (COUNT(*) FROM attachments 
WHERE attachments.nodeid = nodes.id) AS attachmentcount 
FROM nodes
WHERE attachmentcount > 0;
Run Code Online (Sandbox Code Playgroud)

您将在WHERE子句中收到错误"未知列'attachmentcount'".

解决方案实际上非常简单 - 只需用产生别名的语句替换别名,例如:

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;
Run Code Online (Sandbox Code Playgroud)

您仍然会返回别名,但现在SQL不应该使用未知别名.

  • 但是SELECT语句不运行两次吗? (3认同)

M K*_*aid 8

您必须使用该条款aliasWHERE条款不欢迎您定义的内容HAVING

SELECT u_name AS user_name FROM users HAVING user_name = "john";
Run Code Online (Sandbox Code Playgroud)

或者您可以直接使用原始列名称 WHERE

SELECT u_name AS user_name FROM users WHERE u_name = "john";
Run Code Online (Sandbox Code Playgroud)

与由于子查询或任何计算而导致用户定义别名的结果相同,它将由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'
Run Code Online (Sandbox Code Playgroud)


Ste*_*owe 6

更正:

SELECT u_name AS user_name FROM users WHERE u_name = 'john';
Run Code Online (Sandbox Code Playgroud)


Dav*_*dge 6

或者:

SELECT u_name AS user_name
FROM   users
WHERE  u_name = "john";
Run Code Online (Sandbox Code Playgroud)

要么:

SELECT user_name
from
(
SELECT u_name AS user_name
FROM   users
)
WHERE  u_name = "john";
Run Code Online (Sandbox Code Playgroud)

如果RDBMS支持谓词推入内联视图,后者应该与前者相同.


Per*_*eck 5

不需要选择正确的名称.如果你给了表,你可以从别名中选择,但是你可以使用它.


Jar*_*yer 3

你不能。user_name 在返回之前不存在。