Database

MySQL 8.0 의 연산자 우선순위 (Operator Precedence)

헤옹 2023. 3. 11. 22:10

개발을 하면서 AND조건과 OR조건을 함께 사용하다보면 굉장히 혼란스러워질때가 간혹 있다.

내 논리로 예상한 결과값과 실제 MySQL이 검색을 수행한 결과가 다른 건 MySQL이 연산자 우선순위에 따라 처리하기 때문이다.

 

No Operator  
1 INTERVAL SELECT DATE_ADD('2021-07-01', INTERVAL 5 DAY); 과 같이 DATE 연산에 사용되는 연산자
2 BINARY, COLLATE 문자열 비교시 사용하는 연산자
3 !  
4 - (unary minus), ~ (unary bit minus)  
5 ^  
6 *,  /,  DIV,  %,  MOD  
7 -,  +  
8 <<, >>  
9 &  
10 !  
11 =, <=>, >=, <=, <, <>, !=, IS, LIKE,
REGEXP, BETWEEN,
CASE, WHEN, THEN, ELSE
여기서의 =는 할당이 아닌 비교(Comparison) 연산자다
12 NOT  
13 AND, &&  
14 XOR  
15 OR, ||  
16 =, := 여기서의 =는 대입 연산자

참고 : https://dev.mysql.com/doc/refman/8.0/en/operator-precedence.html

 

 

평소에 조회할 때 자주 사용하는 연산자는 아무래도 LIKE, BETWEEN, AND, OR 등 일 것이다.

IS, LIKE, BETEEN > AND  > OR 의 순서로 쿼리를 실행한다는 것을 유의해야 한다.

 

이렇게는 조금 감이 잡히지 않아. 테스트 DB로 실습해보기로 했다.

실습용 데이터는 여기서 구했다 → (https://justinsomnia.org/2009/04/the-emp-and-dept-tables-for-mysql/)

 

 

EMP 테이블

 

위와 같은 EMP 테이블 데이터가 있을 때, 이 쿼리를 실행시킨다고 가정해보자. 만약 MySQL의 연산자 우선순위를 알지못하고 순서대로 조건을 실행할것이라고 생각한다면 다음과 같은 결과를 예상하게 된다.

 

AND (A) ENAME LIKE 'A%' : 이름이 A로 시작하는 직원 (7499, 7876) 2명

OR (B) JOB = 'SALESMAN' : 직업이 SALESMAN인 직원 (7499, 7521, 7654, 7844) 4명을 합집합(UNION)한 결과에

AND DEPTNO != '20' : 부서번호가 20인 직원 (7876)을 제외한 결과로

최종적으로 (7499, ALLEN), (7521, WARD), (7654, MARTIN), (7844, TURNER)를 예상하게 된다.

 

그러나 실제 쿼리 실행 결과는 아래와 같다.

 

어? 위 4행은 이해가는데.. 마지막 ADAMS는 뭐지.. 심지어 부서번호가 20인데..

이런 결과가 나온 이유는 OR 연산자보다 AND 연산자의 우선순위가 더 높기 때문에 JOB = 'SALESMAN' AND DEPTNO != '20' 이 더 먼저 실행되기 때문이다.

 

원래의 쿼리를 이해하기 쉽게 묶어놓자면 아래와 같다. 결국 OR 앞에 있는 조건 - 이름이 'A'로 시작되는 직원에 한에서는 부서번호가 20이 아니라는 제약이 걸리지 않았다.

 

 

따로 실행해보자면 이렇다

 

 

 

이 두 결과의 합집합(중복 제외)인 아래와 같은 결과가 조회된 것이다.

 

 

 

연산자의 우선순위에서 AND가 OR보다 높다는 것이 이해하기에 크게 어렵지 않은 것으로 들리지만.. 가끔 굉장히 헷갈릴 때도 있으니 유의하면서 작성하자!

 

 

끗 ㅎ