고수님들께 쿼리 실행 순서 질문드려요 0 10 4,900

by 리얼디벨러퍼 [MySQL] 실행순서 HAVING SELECT ORDER BY GROUP BY [2015.03.16 01:02:48]


고수님들께
MySQL SELECT, HAVING, ORDER BY 
쿼리 실행 순서 질문드려요

+----+
|   id  |
+----+
|   6   |
|   3   |
|   7   |
|   4   |
|   2   |
|   5   |
|   1   |
|  10 |
|   1   |
|   1   |
|   1   |
|   2   |
+----+
real_title 테이블

> SELECT * FROM real_title, (SELECT @rn:=0) x HAVING (@rn:=@rn+1) = 3 ORDER BY id;
+----+-------+
|   id  | @rn:=0 |
+----+-------+
|   1   |      0    |
+----+-------+

> SELECT * FROM real_title, (SELECT @rn:=0) x WHERE (@rn:=@rn+1) = 3 ORDER BY id;
+----+-------+
|   id  | @rn:=0 |
+----+-------+
|   7   |      0    |
+----+-------+


결과가 위와 같이 나오는데요. 2번째 쿼리는 당연히 ORDER BY 전에 WHERE 절이 실행되야 되니까 이해가 되는데 첫 번째 쿼리의 경우 ORDER BY가 실행된 후에 HAVING이 실행된 것처럼 결과가 출력이 되었네요.
그래서 질문드립니다.

SELECT, GROUP BY, HAVING, ORDER BY의 실행 순서가 어떻게 되나요 ?

질문에 SELECT를 포함한 이유는
> SELECT 'wassup' AS hi FROM (SELECT 1) x WHERE hi = 'wassup';    --  실행 결과 에러 남
> SELECT 'wassup' AS hi FROM (SELECT 1) x HAVING hi = 'wassup';    --  실행 결과 잘 나옴 'wassup'을 출력함

위의 쿼리 결과로 실행 순서가 WHERE -> SELECT -> HAVING 이라 유추했는데 다른 실행순서가 있는지 있는지 궁금하네요.

상황에 따라 달라지는 실행순서 함께 설명해주시면 정말 감사해하며 ID보고 복받으시라고 10번 외치겠습니다..
고수님들 답변 부탁드려요 ~~~~~~~~ !

by DarkBee [2015.03.16 11:37:12]
SELECT    - (5)
  FROM    - (1)
 WHERE    - (2)
 GROUP BY - (3)
 HAVING   - (4)
 ORDER BY - (6)

 


by 마농 [2015.03.16 11:43:48]

MySQL 은 정말 이상하네요.
SQL 표준에서 허용되지 않는 문법이라서...
DarkBee 님 답변은 표준SQL에 대한 답변이구요...
표준을 벗어난 이상한 구문이라서 순서를 논하기가 거시기하네요...


by 리얼디벨러퍼 [2015.03.16 14:24:38]

DarkBee님 마농님 일단 답변 감사드립니다. DarkBee님께서 명시해주신 순서로 저도 외우고 있었는데 MySQL에서는 위의 순서대로 동작되지 않는 상황이 많더군요.
또한, MySQL에서는 Order By 자체도 항상 마지막에 실행되지 않습니다.

예를 들어, 드라이빙 테이블과 드리븐 테이블이 조인해야하는데 인덱스는 타지 못하는 동시에 ORDER BY 에 드라이빙 테이블 컬럼만 명시되어있다면, 드라이빙 테이블 정렬을 한 후에 드리븐 테이블과 조인하고 SELECT 되는 순서입니다. 이와 같은 이유는 문서상에 조인한 후에 정렬을 하면 더 낭비가 심하기 때문이라 명시되어 있습니다. MySQL execution order 관련 질문을 php school에 저번에 올렸는데 답변 받기가 참 힘들군요..


by 마농 [2015.03.16 17:47:15]

위의 순서는 구문을 해석하는 순서입니다.
구문이 실행되는 순서는 또 다른 문제입니다.
구문이 실행되는 순서는 특정하기 어렵습니다.
언급하신 여러 변수에 따라 달라지는 부분이죠.
하지만 구문을 해석하는 순서는 명백하구요.
Oracle과 MSSQL 에서는 구문 해석시 오류가 날 상황인데...
MySQL 은 오류 없이 수행되는게 황당하네요.


by 리얼디벨러퍼 [2015.03.16 20:15:36]

잘 이해가 안가서 그러는데.. 구문을 해석하는 순서와 구문을 실행하는 순서의 차이가 뭐죠?


by 마농 [2015.03.17 08:51:46]

위 순서는 사용자 관점에서 바라보는 논리적인 순서입니다.
오라클 옵티마이져가 구문을 해석하는 순서이구요.
From 절에서 사용된 알리아스를 다음단계에서 사용할 수 있으나
Select 절의 알리아스는 전단계인 Where 나 Having 에서 사용할 수 없죠.
Select 절의 알리아스는 Order By 에서만 사용할 수 있죠.
구문 해석이 끝나면 실행계획을 세우게 되는데요.
실제로 수행되는 물리적인 순서는 이 실행계획에 의해 정해집니다.


by 리얼디벨러퍼 [2015.03.17 09:53:34]

그러면, 오라클에서는 SELECT절에서 정의한 별칭을 GROUP BY에서 사용 못하나요?
 


by DarkBee [2015.03.17 10:12:07]


by 백면서생 [2015.03.17 16:14:45]

-- 경험상 mysql은 좀 독특하게 어지간하면 에러없이 출력되게 설계 된거 같더군요.^^
-- 위에 올려주신 예제 뿐만 아니라

SET @rnum := 0;
SELECT @rnum := @rnum + 1 AS rnum,id,name
FROM mydb.users
ORDER BY id;

-- 이런 구문도 select 절이 먼저 실행되고, 정렬이되어 rnum이 뒤죽박죽 나올거 같지만 
-- 정렬이 먼저 이루어지고 나중에 client fetch 단계에서 numbering이 되는 걸 볼수 있습니다.
-- 아시다시피 정상적인 numbering은 order by 와 같은 쿼리 레벨에 두지 않아야하죠.
-- (보편적으로 ordering을 먼저 하고 view로 묶은 후 밖에서 select 절 numbering 하죠)

-- user variable은 특성상 select 절에서 사용하시고 그 view 외부에서 alias를 
-- 사용하시는게 보편적인 방법이라 생각이 되네요.
-- mysql쪽에서도 user variable을 group by , having, order by 같은 곳에서는 사용하는게
-- 적절치 않다고 이야기 하고 있습니다.(경우에 따라 기대한 결과와 다르게 나오는 경우가 생김)
-- 이야기가 두서없이 늘어졌는데 암튼 제 생각은 sql에서 허용하더라도 보편적인 
-- sql 작성법을 사용하시는게 직관적이라 생각이 듭니다.^^

-- 그리고 mysql에서 위의 예처럼 having에서 select 절 alias를 사용한다던가
-- group by 절에 없는 컬럼이 group function없이 사용된다던가 하는 것(mysql extensions)은
-- sql_mode 시스템변수에 ONLY_FULL_GROUP_BY를 추가 해주시면 다른 dbms처럼
-- error가 생성이 됩니다.

 


by 리얼디벨러퍼 [2015.03.20 09:51:02]

백면서생님 답변 감사합니다.

현재 저는 Real MySQL 책으로 공부하고 있는데, sql표준 문법은 제대로 공부하지 않았고 (그냥 인터넷상으로 훑어봄) 바로 MySQL공부를 시작하였습니다. 보통 MySQL 쿼리 작성 시 다른 RDBMS와 호환이 되도록 sql 표준을 지켜서 작성하나요? 아니면 MySQL의 문법을 살려서 작성하시나요?(sql 표준과 실행 순서가 다르지만 쿼리 실행 순서 체크 후 그대로 사용) 만약 다른 DBMS와 호환이 되도록 쿼리 작성하신다면.. 도움될만한 책이나 싸이트 추천좀 부탁드리겠습니다!

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입