결제 완료 주문만 세려는데 취소 주문이 한 건 끼어 있다. 데이터가 잘못 들어갔나 싶어 행을 다시 봤지만, 문제는 WHERE에 있었다. AND와 OR를 이어 쓴 조건을 사람이 읽은 묶음과 데이터베이스가 평가한 묶음이 달랐다.
WHERE에서 AND와 OR를 그냥 이어 쓰면 어떤 행이 남을까?
서울 또는 부산의 결제 완료 주문을 찾는다고 하자. 예제를 작게 만들어 결과를 끝까지 추적해 보자.
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
status TEXT NOT NULL,
city TEXT NOT NULL
);
INSERT INTO orders (id, status, city) VALUES
(1, 'paid', 'Seoul'),
(2, 'paid', 'Busan'),
(3, 'canceled', 'Busan'),
(4, 'canceled', 'Seoul'),
(5, 'pending', 'Incheon'),
(6, 'paid', 'Incheon');아래 쿼리는 눈으로 훑으면 '결제 완료이면서 서울 또는 부산'처럼 읽히기 쉽다.
SELECT id, status, city
FROM orders
WHERE status = 'paid' AND city = 'Seoul' OR city = 'Busan'
ORDER BY id;id status city
1 paid Seoul
2 paid Busan
3 canceled Busan3번은 취소 주문이다. 이 예제의 SQL 평가에서는 AND가 OR보다 먼저 묶여 조건이 (status = 'paid' AND city = 'Seoul') OR city = 'Busan'처럼 된다. 부산인 행은 상태와 관계없이 오른쪽 조건을 통과한다. 쿼리는 시킨 대로 했고, 우리가 다르게 시킨 셈이다.
그림에서도 괄호가 없는 쪽에만 3번 행이 남는지 확인해 보자.
괄호를 어디에 두면 결제 완료 주문만 남을까?
'결제 완료'는 두 도시 모두에 적용돼야 한다. 먼저 도시 둘을 괄호로 묶자.
SELECT id, status, city
FROM orders
WHERE status = 'paid'
AND (city = 'Seoul' OR city = 'Busan')
ORDER BY id;id status city
1 paid Seoul
2 paid Busan이제 3번 행은 부산이더라도 status = 'paid'를 통과하지 못한다. 괄호는 보기 좋으라고 붙이는 장식이 아니다. 어느 조건을 먼저 한 덩어리로 판단할지 드러낸다.
같은 도시 조건을 IN으로 줄여도 될까?
한 열을 여러 값과 비교한다면 IN이 더 짧다. 지금 예제에서는 괄호를 쓴 쿼리와 같은 두 행이 나온다.
SELECT id, status, city
FROM orders
WHERE status = 'paid'
AND city IN ('Seoul', 'Busan')
ORDER BY id;id status city
1 paid Seoul
2 paid Busan다만 IN은 같은 열의 값 후보를 묶을 때 알맞다. 상태와 날짜처럼 서로 다른 조건까지 한꺼번에 IN으로 바꿀 수는 없다. 그때는 의도한 논리 묶음을 괄호로 써 주는 편이 명확하다.
조건을 바꾼 뒤 어떤 행을 검사해야 할까?
결과가 두 건이라는 숫자만 보면 다른 두 건을 잘못 고른 경우도 놓칠 수 있다. 최소한 들어와야 할 행 두 개와 빠져야 할 행 한 개를 ID로 대조하자. 이 예제에서는 1·2번이 들어오고, '취소+부산'인 3번은 빠져야 한다. '결제+인천'인 6번도 도시 범위 밖이다.
보고서 집계나 접근 범위 필터처럼 WHERE가 결과의 경계를 정한다면, OR 가지가 하나 늘어날 때마다 그 가지에서 빠져야 하는 상태도 시험해야 한다. 쿼리가 실행에 성공했다는 사실과 필요한 행만 남았다는 사실은 다르다.
핵심 요약
AND와 OR를 섞은 WHERE에서 예상 밖의 행이 보이면 조건을 괄호로 다시 읽어 보자. 이 예제의 괄호 없는 조건은 부산의 취소 주문까지 통과시켰다. status = 'paid' AND (city = 'Seoul' OR city = 'Busan')으로 도시를 묶으면 원하는 두 행만 남는다. 같은 열의 값 후보라면 IN으로 간결하게 쓸 수 있고, 수정 뒤에는 건수뿐 아니라 포함·제외돼야 할 행의 ID도 확인한다.
작성자
기초 개념을 구현과 검증, 실제 운영 판단까지 연결해 기록합니다.

