본문 바로가기

Database/MySQL

mysql : 열이름에 alias를 주었을때 그 alias를 조건문으로 또 쓰고 싶다면 having절을 이용하세요.

네, 제목 그대로입니다^^;

http://code.google.com/intl/ko/apis/maps/articles/phpsqlsearch_v3.html 
에 있는 특정 좌표를 중심으로 지정된 거리 반경내의 위치찾기를 구현해놓은 query문을 보다가
where절에 having절을 쓰면서 group by 절또한 쓰지 않아서 헷갈렸었습니다.
이게 맞는 쿼리인가에 대해 약간의 고민이 있었고 그 궁금증을 며칠이나 잊고 있다가 풀었네요 ^^;;
어찌나 게으른지 ㅎㅎ;;; 
SELECT id, ( 3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) * cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) * sin( radians( lat ) ) ) ) AS distance
FROM markers
HAVING distance < 25
ORDER BY distance LIMIT 0 , 20;


위의 쿼리문에서 보라색의 큰 글자의 쿼리문을 보면 select절의 긴 열이름에 distance라는 별칭을 준것이 보입니다.
그리고 having절에서 그 치환한 별칭을 다시 쓰고 있지요.

왜 저러한 쿼리가 나왔는지 이해가 잘 안가서 having 절을 where 절로 바꾸어보았습니다.
그러자 에러가 발생하네요 ^^;;
where절에 쓰인 distance라는 열을 찾지 못하겠다는 에러였습니다.

그리고 order by 절의 별칭을 사용한 것만 내버려두고 having 절을 지워보았더니 정상 출력이 되더군요.

시간관계로 구글링하기전에 짐작컨데
where절의 실행은 select절에 앞서는 것으로 생각됩니다.
즉. from절을 통해서 table을 선택한 후에 select절이 실행되는 것이 아니라 where절이 실행되는 것이지요.
사실 그것이 맞는 것이라는 생각도 듭니다.
왜냐하면 where은 명백히 조건절입니다.
따라서 어떤 table이 선택되었으면 거기에서 열을 선택한 후에 where절이 실행되는 것은
DB입장에서 불필요한 열들까지 계속 가지고 있어야하고 (where절에 선택한 열을 조건으로 넣지 않을 수 있으니까요)
또한 얼마나 많은 양이될지 모르겠지만 불필요한 data를 물고서 where절로 조건에 부합되는지를 검색하게 되니까
불필요한 코스트가 발생하게 되는것이죠.
이러한 이유로 from절 이후에 바로 where절이 실행되는데 이때 위의 distance는 from절에서 얻게된
data의 열 이름이 없으므로 에러가 나는 것으로 생각되네요.

그래서 우선 필요한 data를 from절에서 마련을 해놓고 그 안에서 조건을 통해 적절한 data범위가 정해지면
그 안에서 select를 통한 열을 선택하게 되는 것으로 이해가 되네요.

--3월 14일 08:20부 추가
구글링을 통해서 실행순서를 확인한 바로는 
SELECT       - (5)
FROM         - (1)
WHERE        - (2)
GROUP BY     - (3)
HAVING       - (4)
ORDER BY     - (6) 
이러한 순서의 쿼리 실행순서를 가진다고 합니다. 그럼 여기서 의문점이 생길수밖에 없지요.
분명 저희가 위에서 작성한 쿼리의 별칭정의는 SELECT절에서 실행되었습니다,
그런데 위 내용에 따르면 HAVING절이 우선 실행되는데 저희 쿼리에서는 where절이 막혀 having절을 통해
조건문을 실행한 결과가 나왔지요.
... SELECT 절에 준 별칭정의 순서는 다른 예외케이스이거나 실행순서와는 상관없거나..아님 저 실행순서가 잘못되었거나
뭐 이렇게겠군요... 더 살펴봐야겠어요.
--추가 끝

다만 having절이 group by절 없이도 쓰인다는 사실은 생소하네요.
기회가 되면 다른 DBMS도 살펴보도록 해야겠어요.

추후 구글링을 통해 근거자료를 보충해야겠습니다.