Coluna desconhecida na cláusula Where

126

Eu tenho uma consulta simples:

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

Eu entendo Unknown Column 'user_name' in where clause. Não posso me referir 'user_name'em outras partes da declaração mesmo depois select 'u_name as user_name'?

Btuman
fonte

Respostas:

94

O SQL é avaliado ao contrário, da direita para a esquerda. Portanto, a cláusula where é analisada e avaliada antes da cláusula select. Por esse motivo, o alias de u_name para user_name ainda não ocorreu.

dacracot
fonte
30
Ao invés de "para trás" Eu acho que faz mais sentido dizer "fora para dentro"
Joe Phillips
4
Faz mais sentido dizer que toda a declaração é analisada, transformada e otimizada como um todo em um processo complexo e de vários estágios. "SQL é avaliado ao contrário, da direita para a esquerda" está errado
David Aldridge
3
resposta incompleta quando o usuário perguntou se 'user_name' pode ser usado na instrução, que pode ser posterior a, por exemplo, 'HAVING'
luke_mclachlan
45

A respeito:

SELECT u_name AS user_name FROM users HAVING user_name = "john";
Septimus
fonte
16
Por que você usaria em HAVINGvez de WHEREneste caso?
PeteGO
4
@PeteGO consulte a resposta de Paul Dixon. tldr; HAVING é avaliado depois de WHERE e, mais importante, SELECT.
Jairbow
38

Consulte a seguinte página de manual do MySQL: http://dev.mysql.com/doc/refman/5.0/en/select.html

"Um select_expr pode receber um alias usando AS alias_name. O alias é usado como o nome da coluna da expressão e pode ser usado nas cláusulas GROUP BY, ORDER BY ou HAVING."

(...)

Não é permitido fazer referência a um alias de coluna em uma cláusula WHERE, porque o valor da coluna ainda não pode ser determinado quando a cláusula WHERE for executada. Consulte a Seção B.5.4.4, “Problemas com aliases de coluna”.

Paul Dixon
fonte
Observe também (do homem MySQL): O padrão SQL requer que HAVING faça referência apenas a colunas da cláusula GROUP BY ou colunas usadas em funções agregadas. No entanto, o MySQL suporta uma extensão para esse comportamento e permite que HAVING se refira às colunas na lista SELECT e às colunas nas subconsultas externas.
Vincent Pazeller
12
select u_name as user_name from users where u_name = "john";

Pense assim, sua cláusula where avalia primeiro, para determinar quais linhas (ou linhas unidas) precisam ser retornadas. Depois que a cláusula where é executada, a cláusula select é executada.

Para colocar de uma maneira melhor, imagine o seguinte:

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

Você não pode fazer referência à primeira metade sem a segunda. Onde sempre é avaliado primeiro, depois a cláusula select.

Mark S.
fonte
11

Se você estiver tentando executar uma consulta como a seguinte (encontre todos os nós com pelo menos um anexo) em que você usou uma instrução SELECT para criar um novo campo que não existe realmente no banco de dados e tente usar o alias para esse resultado, você encontrará o mesmo problema:

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

Você receberá um erro "Coluna desconhecida 'attachmentcount' na cláusula WHERE".

A solução é realmente bastante simples - basta substituir o alias pela declaração que produz o alias, por exemplo:

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;

Você ainda receberá o alias retornado, mas agora o SQL não deve trabalhar com o alias desconhecido.

Jon
fonte
1
Eu estava enfrentando esse problema exato e me deparei com sua resposta - obrigado! Apenas para observar, é (compreensivelmente) um pouco lento em bancos de dados grandes, mas estou lidando com uma configuração estúpida de banco de dados herdada.
Liam Newmarch
Acredito que você tenha um extra (na sua consulta antes da (COUNT(*)que não seja fechada em nenhum lugar.
tftd
3
Mas a instrução SELECT não é executada duas vezes?
Matej 25/02
Eu não sou de longe nenhum especialista em mysql, mas isso parece muito pouco desempenho. Eu experimentei que seleções aninhadas tornam uma consulta muito mais lenta.
GDY
8

Seu definido aliasnão é bem-vindo pela WHEREcláusula em que você deve usar a HAVINGcláusula para este

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

OU você pode usar diretamente o nome da coluna original com o WHERE

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

O mesmo que o resultado no alias definido pelo usuário como resultado da subconsulta ou de qualquer cálculo que será acessado pela HAVINGcláusula e não peloWHERE

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'
M Khalid Junaid
fonte
7

Ou:

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

ou:

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

O último deve ser o mesmo que o primeiro se o RDBMS suportar o envio de predicado para a exibição em linha.

David Aldridge
fonte
6

corrigido:

SELECT u_name AS user_name FROM users WHERE u_name = 'john';
Steven A. Lowe
fonte
5

Não, você precisa selecioná-lo com o nome correto. Se você forneceu a tabela que selecionou de um alias, você pode usá-lo.

Per Hornshøj-Schierbeck
fonte
2

Não, você não pode. user_name is não existe até a hora do retorno.

Jarrett Meyer
fonte
1

Coluna desconhecida na WHEREcláusula causada pelas linhas 1 e 2 e resolvida pela linha 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."'";
oliyide
fonte
O que você mudou e por quê? Além disso, por que você postou um código amplamente aberto para injeções de SQL?
Nico Haase
1

Pode ser que ajude.

Você pode

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

Funciona.

MAS TENHA CERTEZA DO QUE VOCÊ FAZ!

  • Os índices NÃO SÃO USADOS aqui
  • Será analisada a TABELA COMPLETA - você não especificou a parte LIMIT 1
  • Então, - ESTA CONSULTA SERÁ INCLUÍDA em grandes mesas.

Mas, pode ser que isso ajude em alguns casos

F_S
fonte
0

Embora você possa criar um alias de suas tabelas em sua consulta (por exemplo, "SELECT u.username FROM users u;"), você deve usar os nomes reais das colunas às quais está fazendo referência. O AS afeta apenas como os campos são retornados.

Blumer
fonte
Eu acho que você pode usar o alias em alguns RDBMS como o MySql, por exemplo. Você está correto para o Sql Server.
PeteGO
0
SELECT user_name
FROM
(
SELECT name AS user_name
FROM   users
) AS test
WHERE  user_name = "john"
Jason Plank
fonte
Por que você deseja usar uma subconsulta? Muito mais simples sem.
PeteGO
0

Só tive esse problema.

Verifique se não há espaço no nome da entidade no banco de dados.

por exemplo, 'nome_do_usuário' em vez de 'nome_do_usuário'

user3103155
fonte
-1

tente sua tarefa usando a condição IN ou OR e também esta consulta está funcionando no spark-1.6.x

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

ou

SELECT  patient, patient_id FROM `patient` WHERE patient = 'User1' OR patient = 'User2';
KARTHIKEYAN.A
fonte
-1

Para mim, a raiz do problema era um número que copiei para usar em uma cláusula WHERE. O número tinha o símbolo "invisível", pelo menos para o MySQL Workbench. Coloquei o número no console do Chrome que estava claramente visível.

Vi0nik
fonte
-2

Eu tive o mesmo problema, achei isso útil.

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

lembre-se de colocar $ user em '' aspas simples.

devWaleed
fonte
1
Esse código é amplamente aberto para injeção de SQL. Ninguém deve usar este código para resolver o problema dado
Nico Haase