MySQLのクエリの句がエラーを生成しますWHEREで使用する列の別名
-
09-09-2019 - |
質問
私が実行しているクエリがあり、次のように、しかし、私はこのエラーを取得しています:
#1054 - 不明な列 'guaranteed_postcode' 'IN / ALL / ANYサブクエリ'
SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`,
SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode`
FROM `users` LEFT OUTER JOIN `locations`
ON `users`.`id` = `locations`.`user_id`
WHERE `guaranteed_postcode` NOT IN #this is where the fake col is being used
(
SELECT `postcode` FROM `postcodes` WHERE `region` IN
(
'australia'
)
)
私の質問は:なぜ私は同じDBクエリのWHERE句に偽の列を使用することができません。
?解決
あなただけのGROUP BY、ORDER BY、またはHAVING句で列の別名を使用することができます。
標準SQLは、あなたがすることはできません。 WHEREで列の別名を参照してください。 句。この制限は課され WHEREコードがあるとき理由 実行され、列の値がまだないかもしれません 決定されます。
MySQLのドキュメントのからコピーP> コメントで指摘したように、
、代わりにHAVING使用して作業を行うことができます。この WHEREしかしのHAVING対にしてくださいます。
他のヒント
、問題が別名です。これは、WHERE xのyの句に式を直接置くことによって、しかし回避することができます:
SELECT `users`.`first_name`,`users`.`last_name`,`users`.`email`,SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode`
FROM `users` LEFT OUTER JOIN `locations`
ON `users`.`id` = `locations`.`user_id`
WHERE SUBSTRING(`locations`.`raw`,-6,4) NOT IN #this is where the fake col is being used
(
SELECT `postcode` FROM `postcodes` WHERE `region` IN
(
'australia'
)
)
しかし、私は、サブクエリは外部クエリのすべての行に対して実行されなければならないので、これは、非常に非効率的であると思います。
標準SQL(またはMySQLは)WHERE句で列の別名の使用を許可していません
WHERE句が評価されたときに、、列の値がまだ決定されていない可能性があります。
( MySQLのドキュメントするから) 。あなたにできることは、のの句で列の値を計算し、変数に値を保存し、フィールドリストでそれを使用しています。たとえば、あなたがこれを行うことができます:
SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`,
@postcode AS `guaranteed_postcode`
FROM `users` LEFT OUTER JOIN `locations`
ON `users`.`id` = `locations`.`user_id`
WHERE (@postcode := SUBSTRING(`locations`.`raw`,-6,4)) NOT IN
(
SELECT `postcode` FROM `postcodes` WHERE `region` IN
(
'australia'
)
)
これは、複雑な成長したときに維持しやすいコードを作り、式を繰り返し避けます。
たぶん、私の答えは手遅れであるが、これは他の人を助けることができます。
あなたは別のselect文でそれを囲み、それにwhere句を使用することができます。
SELECT * FROM (Select col1, col2,...) as t WHERE t.calcAlias > 0
calcAliasを算出したエイリアスカラムである。
あなたは、SELECTフィールドと別名で算出されたフィルタのためにHAVING句を使用することができます。
私は、MySQL 5.5.24を使用していますし、次のコードは動作します:
select * from (
SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`,
SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode`
FROM `users` LEFT OUTER JOIN `locations`
ON `users`.`id` = `locations`.`user_id`
) as a
WHERE guaranteed_postcode NOT IN --this is where the fake col is being used
(
SELECT `postcode` FROM `postcodes` WHERE `region` IN
(
'australia'
)
)
標準SQLはWHERE句で列の別名への参照を禁止します。 WHERE句が評価されるとき、列の値がまだ決定されていないかもしれないので、この制限が課されます。たとえば、次のクエリは違法です。
SELECT ID、COUNT(*)IDでtbl_nameをWHERE CNT> 0群からCNT AS;
あなたはどこ条件のSUBSTRING(locations
.raw
、-6,4)を使用することができます。
SELECT `users`.`first_name`, `users`.`last_name`, `users`.`email`,
SUBSTRING(`locations`.`raw`,-6,4) AS `guaranteed_postcode`
FROM `users` LEFT OUTER JOIN `locations`
ON `users`.`id` = `locations`.`user_id`
WHERE SUBSTRING(`locations`.`raw`,-6,4) NOT IN #this is where the fake col is being used
(
SELECT `postcode` FROM `postcodes` WHERE `region` IN
(
'australia'
)
)