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
「逆方向」ではなく、「裏返し」と言った方が理にかなっていると思います
Joe Phillips

4
ステートメント全体が、複雑なマルチステージプロセスで全体として解析、変換、および最適化されると言う方が理にかなっています。「SQLは右から左に逆方向に評価されます」は間違っています
David Aldridge '28

3
ステートメントで 'user_name'を使用できるかどうかをユーザーが尋ねたため、不完全な回答です。たとえば、 'HAVING'
luke_mclachlan

45

何について:

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

16
この場合のHAVING代わりになぜ使用するのWHEREですか?
PeteGO 2014

4
@PeteGOはPaul Dixonの回答を参照しています。tldr; HAVINGはWHEREよりも後に評価され、さらに重要なのはSELECTです。
jairbow 2017年

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リストの列と外部サブクエリの列を参照することを許可しています。
Vincent Pazeller 2017

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

次のようなクエリを実行しようとしている場合(少なくとも1つのアタッチメントを持つすべてのノードを検索)、SELECTステートメントを使用して、実際にはデータベースに存在しない新しいフィールドを作成し、その結果のエイリアスで同じ問題が発生します。

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

「不明な列 'attachmentcount' in 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
私はこの正確な問題に直面していて、あなたの答えに出くわしました-ありがとう!ちょうど注意してください、それは大規模なデータベースでは(当然のことながら)少し遅いですが、私はとにかく愚かな継承されたデータベースのセットアップを扱っています。
リアムニューマーチ2011

私はあなたが(あなたのクエリの前に余分な(COUNT(*)ものがあり、それがどこでも閉じられていないと信じています。
tftd

3
しかし、SELECTステートメントは2回実行されませんか?
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";

RDBMSが述語をインラインビューにプッシュすることをサポートしている場合、後者は前者と同じであるべきです。





1

WHERE1行目と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インジェクションに対して広く開かれているコードを投稿したのはなぜですか?
Nico Haase

1

それが役立つかもしれません。

あなたはできる

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

できます。

しかし、あなたが何をすべきかを確認してください!

  • ここではインデックスは使用されません
  • フルテーブルがスキャンされます-LIMIT 1パーツが指定されていません
  • したがって、このクエリは巨大なテーブルではSLLLOOOOOOWになります。

しかし、場合によっては役立つかもしれません


0

クエリ内でテーブルにエイリアスを設定することはできますが(つまり、「SELECT u.username FROM users u;」)、参照している列の実際の名前を使用する必要があります。ASは、フィールドが返される方法にのみ影響します。


MySqlなどの一部のRDBMSでエイリアスを使用できると思います。しかし、あなたはSQL Serverに適しています。
PeteGO 2014


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インジェクションに対して広く開かれています。特定の問題を解決するためにこのコードを使用するべきではありません
Nico Haase
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.