私が実行しているクエリは次のとおりですが、このエラーが発生しています:
#1054-「IN/ALL/ANY subquery」の不明な列「guaranteed_postcode」
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ドキュメント からコピー
コメントで指摘したように、代わりにHAVINGを使用することで機能する場合があります。ただし、この点については必ず読んでください WHERE vs HAVING .
ビクターが指摘したように、問題はエイリアスにあります。ただし、式をWHERE x IN 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ドキュメント から)。できることは、WHERE句で列の値を計算し、値を変数に保存して、フィールドリストで使用することです。たとえば、これを行うことができます:
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(*)AS cnt FROM tbl_name WHERE cnt> 0 GROUP BY id;
条件として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'
)
)