web-dev-qa-db-ja.com

MySQLクエリのWHERE句で列エイリアスを使用するとエラーが発生する

私が実行しているクエリは次のとおりですが、このエラーが発生しています:

#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句で偽の列を使用できないのはなぜですか?

169
James

GROUP BY、ORDER BY、またはHAVING句でのみ列エイリアスを使用できます。

標準SQLでは、WHERE句で列エイリアスを参照することはできません。 WHEREコードが実行されるとき、列の値がまだ決定されていない可能性があるため、この制限が課せられます。

MySQLドキュメント からコピー

コメントで指摘したように、代わりにHAVINGを使用することで機能する場合があります。ただし、この点については必ず読んでください WHERE vs HAVING .

389
victor hugo

ビクターが指摘したように、問題はエイリアスにあります。ただし、式を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'
 )
)

ただし、外部クエリのすべての行に対してサブクエリを実行する必要があるため、これは非常に効率が悪いと思います。

23
rodion

標準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'
 )
)

これにより、式が複雑になったときに式を繰り返すことを避け、コードの保守を容易にします。

18
Joni

多分私の答えは手遅れですが、これは他の人を助けることができます。

別のselect文で囲み、where句を使用できます。

SELECT * FROM (Select col1, col2,...) as t WHERE t.calcAlias > 0

calcAliasは、計算されたエイリアス列です。

13
George Khouri

SELECTフィールドとエイリアスで計算されたフィルターにHAVING句を使用できます

8
Hett

私は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'
 )
)
1
themis

標準SQLでは、WHERE句の列エイリアスへの参照は許可されていません。 WHERE句が評価されるとき、列の値がまだ決定されていない可能性があるため、この制限が課せられます。たとえば、次のクエリは無効です。

SELECT id、COUNT(*)AS cnt FROM tbl_name WHERE cnt> 0 GROUP BY id;

0
Pavan Rajput

条件として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'
)
)