Kolom Tidak Diketahui Di Dalam Klausa Dimana

126

Saya punya pertanyaan sederhana:

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

Saya mengerti Unknown Column 'user_name' in where clause. Tidak dapatkah saya merujuk ke 'user_name'bagian lain dari pernyataan bahkan setelahnya select 'u_name as user_name'?

Btuman
sumber

Jawaban:

94

SQL dievaluasi mundur, dari kanan ke kiri. Jadi klausa where diurai dan dievaluasi sebelum klausa pilih. Karena itu, aliasing u_name ke user_name belum terjadi.

dacracot.dll
sumber
30
Daripada "mundur", saya pikir lebih masuk akal untuk mengatakan "dari dalam ke luar"
Joe Phillips
4
Lebih masuk akal untuk mengatakan bahwa seluruh pernyataan diurai, diubah, dan dioptimalkan secara keseluruhan dalam proses multistage yang kompleks. "SQL dievaluasi mundur, dari kanan ke kiri" adalah salah
David Aldridge
3
jawaban tidak lengkap saat pengguna bertanya apakah 'nama_pengguna' dapat digunakan dalam pernyataan, yang bisa setelah misalnya 'HAVING'
luke_mclachlan
45

Bagaimana dengan:

SELECT u_name AS user_name FROM users HAVING user_name = "john";
Septimus
sumber
16
Mengapa Anda menggunakan, HAVINGbukan WHEREdalam kasus ini?
PeteGO
4
@PeteGO mengacu pada jawaban Paul Dixon. tldr; HAVING dievaluasi lebih lambat dari WHERE dan, yang lebih penting, SELECT.
jairbow
38

Lihat halaman manual MySQL berikut ini: http://dev.mysql.com/doc/refman/5.0/en/select.html

"Sebuah select_expr dapat diberi alias menggunakan AS alias_name. Alias ​​tersebut digunakan sebagai nama kolom ekspresi dan dapat digunakan dalam klausa GROUP BY, ORDER BY, atau HAVING."

(...)

Tidak diizinkan untuk merujuk ke alias kolom dalam klausa WHERE, karena nilai kolom mungkin belum ditentukan saat klausa WHERE dijalankan. Lihat Bagian B.5.4.4, “Masalah dengan Alias ​​Kolom”.

Paul Dixon
sumber
Juga, catatan (dari MySQL man): Standar SQL mengharuskan HAVING harus mereferensikan hanya kolom dalam klausa GROUP BY atau kolom yang digunakan dalam fungsi agregat. Namun, MySQL mendukung ekstensi untuk perilaku ini, dan mengizinkan HAVING untuk merujuk ke kolom dalam daftar PILIHAN dan kolom di subkueri luar juga.
Vincent Pazeller
12
select u_name as user_name from users where u_name = "john";

Anggap saja seperti ini, klausa where Anda mengevaluasi terlebih dahulu, untuk menentukan baris mana (atau baris gabungan) yang perlu dikembalikan. Setelah klausa where dijalankan, klausa pemilihan berjalan untuknya.

Sederhananya, bayangkan ini:

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

Anda tidak dapat mereferensikan paruh pertama tanpa yang kedua. Di mana selalu dievaluasi terlebih dahulu, lalu klausa pilih.

Tanda.
sumber
11

Jika Anda mencoba melakukan kueri seperti berikut (temukan semua node dengan setidaknya satu lampiran) di mana Anda telah menggunakan pernyataan SELECT untuk membuat bidang baru yang sebenarnya tidak ada dalam database, dan coba gunakan alias untuk hasil itu Anda akan mengalami masalah yang sama:

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

Anda akan mendapatkan error "Kolom tidak diketahui 'attachmentcount' di klausa WHERE".

Solusi sebenarnya cukup sederhana - cukup ganti alias dengan pernyataan yang menghasilkan alias, misalnya:

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;

Anda masih akan mendapatkan alias kembali, tetapi sekarang SQL tidak boleh mengganggu alias tidak dikenal.

Jon
sumber
1
Saya menghadapi masalah ini, dan menemukan jawaban Anda - terima kasih! Sekadar catatan, ini (dapat dimengerti) agak lambat pada database besar, tapi saya berurusan dengan pengaturan database warisan yang bodoh.
Liam Newmarch
Saya yakin Anda memiliki tambahan (dalam kueri Anda sebelum (COUNT(*)yang tidak ditutup di mana pun.
tftd
3
Tetapi bukankah pernyataan SELECT dijalankan dua kali?
Matej
Sejauh ini saya bukan ahli mysql tetapi tampaknya ini sangat tidak dalam format. Saya pernah mengalami bahwa pemilihan bersarang membuat kueri jauh lebih lambat.
GDY
8

Definisi Anda aliastidak disambut oleh WHEREklausa Anda harus menggunakan HAVINGklausa untuk ini

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

ATAU Anda bisa langsung menggunakan nama kolom asli dengan WHERE

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

Sama seperti Anda memiliki hasil dalam alias yang ditentukan pengguna sebagai hasil dari subquery atau perhitungan apa pun, itu akan diakses oleh HAVINGklausa bukan olehWHERE

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
sumber
7

Antara:

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

atau:

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

Yang terakhir harus sama dengan yang pertama jika RDBMS mendukung dorongan predikat ke dalam tampilan in-line.

David Aldridge
sumber
6

dikoreksi:

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

Tidak, Anda perlu memilihnya dengan nama yang benar. Jika Anda memberikan tabel yang Anda pilih dari alias, Anda dapat menggunakannya.

Per Hornshøj-Schierbeck
sumber
2

Tidak Anda tidak bisa. user_name tidak ada sampai waktu kembali.

Jarrett Meyer
sumber
1

Kolom tidak diketahui dalam WHEREklausa yang disebabkan oleh baris 1 dan 2 dan diselesaikan oleh baris 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.dll
sumber
Apa yang telah Anda ubah dan mengapa? Selain itu, mengapa Anda memposting kode yang terbuka untuk injeksi SQL?
Nico Haase
1

Mungkin bisa membantu.

Kamu bisa

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

Berhasil.

TAPI PASTIKAN APA YANG ANDA LAKUKAN!

  • Indeks TIDAK DIGUNAKAN di sini
  • Akan ada TABEL LENGKAP yang dipindai - Anda belum menentukan bagian LIMIT 1
  • Jadi, - QUERY INI AKAN SLLLOOOOOOW di meja-meja besar.

Tapi, mungkin itu membantu dalam beberapa kasus

F_S
sumber
0

Meskipun Anda dapat membuat alias tabel di dalam kueri Anda (yaitu, "PILIH u.username FROM users u;"), Anda harus menggunakan nama sebenarnya dari kolom yang Anda referensikan. AS hanya memengaruhi bagaimana bidang dikembalikan.

Blumer
sumber
Saya rasa Anda dapat menggunakan alias di beberapa RDBMS seperti MySql misalnya. Anda benar untuk Sql Server.
PeteGO
0
SELECT user_name
FROM
(
SELECT name AS user_name
FROM   users
) AS test
WHERE  user_name = "john"
Jason Plank
sumber
Mengapa Anda ingin menggunakan sub-kueri? Jauh lebih sederhana tanpa.
PeteGO
0

Baru saja mengalami masalah ini.

Pastikan tidak ada spasi di nama entitas di database.

misalnya 'user_name' bukan 'user_name'

pengguna3103155
sumber
-1

coba tugas Anda menggunakan kondisi IN atau OR dan juga kueri ini bekerja di spark-1.6.x

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

atau

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

Bagi saya, akar masalahnya adalah angka yang saya salin untuk digunakan dalam klausa WHERE. Nomor itu memiliki simbol "tidak terlihat", setidaknya untuk MySQL Workbench. Saya menempatkan nomor di konsol Chrome itu terlihat jelas.

Vi0nik
sumber
-2

Saya memiliki masalah yang sama, saya merasa ini berguna.

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

ingat untuk memasukkan $ user dalam tanda kutip tunggal ''.

devWaleed
sumber
1
Kode itu terbuka lebar untuk injeksi SQL. Tidak ada yang boleh menggunakan kode ini untuk memecahkan masalah yang diberikan
Nico Haase