Nieznana kolumna w klauzuli gdzie

126

Mam proste zapytanie:

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

Rozumiem Unknown Column 'user_name' in where clause. Czy nie mogę odnieść się do 'user_name'innych części oświadczenia nawet po select 'u_name as user_name'?

Btuman
źródło

Odpowiedzi:

94

SQL jest oceniany wstecz, od prawej do lewej. Zatem klauzula where jest analizowana i szacowana przed klauzulą ​​select. Z tego powodu aliasowanie nazwy u_nazwa_użytkownika jeszcze nie nastąpiło.

dacracot
źródło
30
Myślę, że bardziej sensowne jest powiedzenie „na lewą stronę” niż „wstecz”
Joe Phillips
4
Bardziej sensowne jest stwierdzenie, że cała instrukcja jest analizowana, przekształcana i optymalizowana jako całość w złożonym, wieloetapowym procesie. „SQL jest oceniany wstecz, od prawej do lewej” jest po prostu błędne
David Aldridge,
3
niepełna odpowiedź, ponieważ użytkownik zapytał, czy w instrukcji można użyć wyrażenia „nazwa_użytkownika”, co może być np. po „HAVING”
luke_mclachlan
45

Co powiesz na:

SELECT u_name AS user_name FROM users HAVING user_name = "john";
Septimus
źródło
16
Dlaczego miałbyś używać HAVINGzamiast WHEREw tym przypadku?
PeteGO
4
@PeteGO odnoszą się do odpowiedzi Paula Dixona. tldr; HAVING jest oceniana później niż WHERE i, co ważniejsze, SELECT.
jairbow
38

Zobacz następującą stronę podręcznika MySQL: http://dev.mysql.com/doc/refman/5.0/en/select.html

„Select_expr można nadać alias za pomocą AS alias_name. Alias ​​jest używany jako nazwa kolumny wyrażenia i może być używany w klauzulach GROUP BY, ORDER BY lub HAVING.”

(...)

Niedopuszczalne jest odwoływanie się do aliasu kolumny w klauzuli WHERE, ponieważ wartość kolumny może nie zostać jeszcze określona podczas wykonywania klauzuli WHERE. Zobacz Sekcja B.5.4.4, „Problemy z aliasami kolumn”.

Paul Dixon
źródło
Uwaga (od człowieka MySQL): Standard SQL wymaga, aby HAVING odnosiło się tylko do kolumn w klauzuli GROUP BY lub kolumn używanych w funkcjach agregujących. Jednak MySQL obsługuje rozszerzenie tego zachowania i pozwala MIEĆ odwoływanie się do kolumn na liście WYBIERZ, a także do kolumn w zewnętrznych podzapytaniach.
Vincent Pazeller
12
select u_name as user_name from users where u_name = "john";

Pomyśl o tym w ten sposób, Twoja klauzula where jest obliczana jako pierwsza, aby określić, które wiersze (lub połączone wiersze) mają zostać zwrócone. Po wykonaniu klauzuli where, klauzula select jest uruchamiana dla niej.

Ujmując to lepiej, wyobraź sobie to:

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

Nie możesz odwołać się do pierwszej połowy bez drugiej. Gdzie zawsze jest oceniany jako pierwszy, a następnie klauzula select.

Znaki.
źródło
11

Jeśli próbujesz wykonać zapytanie podobne do poniższego (znajdź wszystkie węzły z co najmniej jednym załącznikiem), w którym użyłeś instrukcji SELECT, aby utworzyć nowe pole, które faktycznie nie istnieje w bazie danych, i spróbuj użyć alias dla tego wyniku napotkasz ten sam problem:

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

W klauzuli WHERE pojawi się błąd „Nieznana kolumna„ filecount ””.

Rozwiązanie jest właściwie dość proste - wystarczy zamienić alias na instrukcję, która tworzy alias, np .:

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;

Nadal otrzymasz zwrócony alias, ale teraz SQL nie powinien działać na nieznanym aliasie.

Jon
źródło
1
Miałem dokładnie ten problem i znalazłem twoją odpowiedź - dziękuję! Warto zauważyć, że jest to (co zrozumiałe) trochę powolne w przypadku dużych baz danych, ale i tak mam do czynienia z głupią konfiguracją dziedziczonej bazy danych.
Liam Newmarch
Wydaje mi się, że masz (w zapytaniu dodatek, (COUNT(*)który nie jest nigdzie zamknięty.
tftd
3
Ale czy instrukcja SELECT nie jest uruchamiana dwukrotnie?
Matej
Zdecydowanie nie jestem ekspertem od mysql, ale wydaje się to bardzo nieefektywne. Doświadczyłem, że zagnieżdżone selekcje znacznie spowalniają zapytanie.
GDY
8

Zdefiniowane aliasprzez WHERECiebie nie są mile widziane przez klauzulę, w której musisz użyć HAVINGklauzuli

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

LUB możesz bezpośrednio użyć oryginalnej nazwy kolumny z rozszerzeniem WHERE

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

Tak samo, jak w przypadku wyniku w aliasie zdefiniowanym przez użytkownika w wyniku podzapytania lub dowolnego obliczenia, dostęp do niego będzie możliwy przez HAVINGklauzulę, a nie przezWHERE

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
źródło
7

Zarówno:

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

lub:

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

Ten drugi powinien być taki sam jak pierwszy, jeśli RDBMS obsługuje wypychanie predykatów do widoku in-line.

David Aldridge
źródło
6

poprawione:

SELECT u_name AS user_name FROM users WHERE u_name = 'john';
Steven A. Lowe
źródło
5

Nie, musisz go wybrać z poprawną nazwą. Jeśli podałeś tabelę, którą wybierzesz z aliasu, możesz tego użyć.

Per Hornshøj-Schierbeck
źródło
2

Nie, nie możesz. nazwa_użytkownika nie istnieje do czasu powrotu.

Jarrett Meyer
źródło
1

Nieznana kolumna w WHEREklauzuli spowodowana liniami 1 i 2 i rozwiązana przez linię 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
źródło
Co zmieniłeś i dlaczego? Ponadto, dlaczego wysłałeś kod, który jest szeroko otwarty na iniekcje SQL?
Nico Haase
1

Może to pomoże.

Możesz

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

To działa.

ALE UPEWNIJ SIĘ, CO ROBISZ!

  • Indeksy NIE SĄ UŻYWANE tutaj
  • Zostanie zeskanowana PEŁNA TABELA - nie określiłeś części LIMIT 1
  • A więc - TO ZAPYTANIE BĘDZIE WYGLĄDAŁO NA DUŻYCH stołach.

Ale może w niektórych przypadkach to pomaga

F_S
źródło
0

Chociaż możesz aliasować swoje tabele w zapytaniu (np. „SELECT u.username FROM users u;”), musisz użyć rzeczywistych nazw kolumn, do których się odnosisz. AS wpływa tylko na sposób zwracania pól.

Blumer
źródło
Myślę, że możesz użyć aliasu w niektórych RDBMS, takich jak na przykład MySql. Masz jednak rację dla Sql Server.
PeteGO
0
SELECT user_name
FROM
(
SELECT name AS user_name
FROM   users
) AS test
WHERE  user_name = "john"
Jason Plank
źródło
Dlaczego chcesz użyć zapytania podrzędnego? O wiele prostsze bez.
PeteGO
0

Właśnie miałem ten problem.

Upewnij się, że w nazwie jednostki w bazie danych nie ma spacji.

np. „nazwa_użytkownika” zamiast „nazwa_użytkownika”

user3103155
źródło
-1

wypróbuj swoje zadanie używając warunku IN lub warunku OR , a także to zapytanie działa na spark-1.6.x

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

lub

SELECT  patient, patient_id FROM `patient` WHERE patient = 'User1' OR patient = 'User2';
KARTHIKEYAN.A
źródło
-1

Dla mnie źródłem problemu była liczba, którą skopiowałem, aby użyć w klauzuli WHERE. Liczba miała symbol „niewidoczny”, przynajmniej dla MySQL Workbench. Numer umieściłem w konsoli Chrome, żeby był dobrze widoczny.

Vi0nik
źródło
-2

Miałem ten sam problem, uznałem to za przydatne.

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

pamiętaj, aby umieścić $ user w pojedynczych cudzysłowach.

devWaleed
źródło
1
Ten kod jest szeroko otwarty do iniekcji SQL. Nikt nie powinien używać tego kodu do rozwiązania danego problemu
Nico Haase