MySQL 쿼리의 WHERE 절에서 열 별칭을 사용하면 오류가 발생합니다


201

내가 실행중인 쿼리는 다음과 같지만이 오류가 발생합니다.

# 1054- 'IN / ALL / ANY 하위 쿼리'의 알 수없는 열 '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 절에서 가짜 열을 사용할 수 없습니까?

답변:


434

GROUP BY, ORDER BY 또는 HAVING 절에는 열 별명 만 사용할 수 있습니다.

표준 SQL을 사용하면 WHERE 절에서 열 별칭을 참조 할 수 없습니다. WHERE 코드가 실행될 때 열 값이 아직 결정되지 않았기 때문에 이러한 제한이 적용됩니다.

MySQL 문서 에서 복사

주석에서 지적했듯이 HAVING을 대신 사용하면 작업을 수행 할 수 있습니다. 이 WHERE vs HAVING을 읽으십시오 .


1
빠르고 정확한 답변을 응원합니다! HAVING 절을 살펴 보고이 쿼리를 성공적으로 실행하는 방법을 찾았습니다. 다시 감사합니다.
James

38
다른 사람이 where 절에서 별칭이 지정된 열을 사용하고있는 것과 같은 문제가있는 경우 'HAVING'을 'WHERE'로 바꾸면 즉시 +1 좋은 답변이 수정되었습니다.
megaSteve4

@ megaSteve4 나는 같은 문제가 있었다! "HAVING"을 사용하면 문제가 해결되었습니다. :)
Johan

9
이것은 귀하의 경우에 중요하거나 중요하지 않을 수 있지만, HAVING느리게 실행됩니다WHERE
DTs

1
having작동 하는 이유 는에 도달 할 때까지 열 값을 계산해야하기 때문 having입니다. where위에서 언급 한 것처럼 이 경우에는 그렇지 않습니다 .
Millie Smith

24

Victor가 지적했듯이 문제는 별칭입니다. 그러나 표현식을 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'
 )
)

그러나 외부 쿼리의 모든 행에 대해 하위 쿼리를 실행해야하기 때문에 이것이 매우 비효율적이라고 생각합니다.


1
@ rodion, 예 나는 이것이 매우 느리고 비효율적 이라고 생각합니다 .
Pacerier

20

표준 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'
 )
)

이렇게하면식이 복잡해질 때 반복되는 표현을 피할 수있어 코드를보다 쉽게 ​​관리 할 수 ​​있습니다.


9
문서이 충돌하지 않는 말한다 "일반적으로, 당신은 사용자 변수에 값을 할당하지 않고 동일한 명령문 내에서 값을 읽을 안가. 당신은 당신이 기대하는 결과를 얻을 수 있지만이 보장되지 않습니다." ?
Arjan

그것은 분명히 명심해야 할 것입니다. 그것은 항상 나를 위해 일해 왔지만, 진술의 다른 부분에 대한 평가 순서는 고정되어야한다고 생각합니다 (먼저 WHERE, SELECT, GROUP BY 등). 그러나 나는 그것에 대한 참조가 없습니다.
Joni

몇 가지 예 : 일부 주장 그들을 위해 것을 select @code:=sum(2), 2*@code5.6에서의 MySQL 5.5에서 작동하지만 나를 위해 첫 번째 호출에 두 번째 열 생산량의 NULL, 반환 2 회 이전 결과 를 다시 실행합니다. 충분히 흥미롭고 선택 @code:=2, 2*@codeselect @code:=rand(), 2*@code행동 모두 5.6 (오늘)에서 작동하는 것 같습니다. 그러나 이들은 실제로 SELECT 절에서 쓰고 읽고 있습니다. 귀하의 경우에는 어디에서 설정합니까?
Arjan

@ 조니, 왜 조건을 두 번 평가하지 않습니까? 확실히 MySQL은 그것을 최적화하기에 충분히 똑똑합니다 .......
Pacerier

@Pacerier가 표현을 반복해야하는 것은 특히 복잡한 경우에는 여전히 더 나쁩니다. MySQL이 일반적인 하위 식 제거를 구현하는지 확인할 수 없었습니다.
Joni

16

어쩌면 내 대답이 너무 늦었지만 다른 사람들을 도울 수 있습니다.

다른 select 문으로 묶고 where 절을 사용할 수 있습니다.

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

calcAlias는 계산 된 별명 열입니다.


멋지고 짧지 만 유용하지 않기에는 너무 모호합니다.
Agamemnus 2014

@Agamemnus, 그게 무슨 소리 야?
Pacerier

문제는 "동일한 DB 쿼리의 where 절에서 가짜 열을 사용할 수없는 이유는 무엇입니까?"였습니다. 이 답변은 그 질문에 대한 답이 아니며 동사가 없습니다.
Agamemnus

그런 다음 단순히 HAVING
Hett

8

SELECT 필드 및 별명에서 계산 된 필터에 HAVING 절을 사용할 수 있습니다.


@ fahimg23-확실하지 않습니다. 이유를 찾으려고했지만 할 수 없습니다! 사이에 마음의 차이를 유지 WHERE하고 HAVING있지만. 그들은 동일하지 않습니다. stackoverflow.com/search?q=where+vs+having
rinogo

업데이트 : 이 답변 은 동일한 솔루션을 제공하지만 더 많은 정보를 제공 하기 때문 입니다.
rinogo 2016 년

1

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

0

표준 SQL은 WHERE 절에서 열 별칭에 대한 참조를 허용하지 않습니다. WHERE 절을 평가할 때 열 값이 아직 결정되지 않았기 때문에이 제한이 적용됩니다. 예를 들어, 다음 쿼리는 불법입니다.

ID를 선택하십시오. tbl_name에서 cnt를 기준으로 COUNT (*) cnt> 0 GROUP BY ID;


0

당신은 문자열을 사용할 수 있습니다 ( 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'
)
)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.