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*@code과 select @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.