Search
moon
sun

08.WHERE절과 연산자

•
WHERE절로 원하는 행만 골라낼 수 있다.
•
BETWEEN · IN · LIKE · IS NULL 네 가지 SQL 연산자를 상황에 맞게 쓸 수 있다.
•
LIKE의 와일드카드 % 와 _ 의 차이를 알고 결과를 예측할 수 있다.
•
AND가 OR보다 우선순위가 높다는 것을 알고 괄호를 올바르게 쓸 수 있다.
•
NOT IN 목록에 NULL이 있으면 결과가 0건이 되는 이유를 설명할 수 있다.

1. WHERE절의 역할

1) 행을 걸러내는 필터

SELECT 컬럼명 -- ⑤ 어떤 컬럼을 볼지 FROM 테이블명 -- ① 어느 테이블에서 WHERE 조건식; -- ② 어떤 행만 남길지 ← 오늘의 주제
SQL
복사
-- ============================================================ -- 【이해용 예제】 조건을 붙이면 결과가 어떻게 줄어드는가 -- ============================================================ -- (1) 조건 없이 전체 조회 SELECT ENAME, DEPTNO, SAL FROM EMP; -- WHERE 가 없으면 모든 행이 나온다 -- → 14건 -- (2) 부서번호가 20인 사원만 SELECT ENAME, DEPTNO, SAL FROM EMP WHERE DEPTNO = 20; -- DEPTNO 값이 20인 행만 통과 -- ENAME DEPTNO SAL -- ----- ------ ----- -- SMITH 20 800 -- JONES 20 2975 -- SCOTT 20 3000 -- ADAMS 20 1100 -- FORD 20 3000 → 5건 -- (3) 조건을 더 붙이면 더 줄어든다 SELECT ENAME, DEPTNO, SAL FROM EMP WHERE DEPTNO = 20 -- 조건 ① AND SAL >= 3000; -- 조건 ② (AND 로 연결 → 둘 다 만족해야 함) -- ENAME DEPTNO SAL -- ----- ------ ----- -- SCOTT 20 3000 -- FORD 20 3000 → 2건
SQL
복사

2. 비교 연산자

1) 종류

연산자
의미
예
=
같다
DEPTNO = 20
>
크다
SAL > 3000
>=
크거나 같다
SAL >= 3000
<
작다
SAL < 1000
<=
작거나 같다
SAL <= 1000
<> != ^=
같지 않다 (셋 다 동일) ⭐
JOB <> 'CLERK'
⚠️ 시험 포인트: <> != ^= 는 완전히 같은 의미입니다. 표준 SQL 표기는 <> 이며, Oracle에서는 셋 다 동작합니다.

2) 문자·날짜 비교 시 주의점

-- ============================================================ -- 【시험용 예제】 문자와 날짜를 비교할 때의 함정 ★ -- ============================================================ -- ⚠️ 함정 ① 문자열은 대소문자를 구분한다 (07강 회수) SELECT ENAME FROM EMP WHERE ENAME = 'smith'; -- → 0건! 실제 저장된 값은 'SMITH' 이다 SELECT ENAME FROM EMP WHERE ENAME = 'SMITH'; -- ENAME -- ----- -- SMITH → 1건 ✅ -- ⚠️ 함정 ② 문자는 '사전 순'으로 비교된다 SELECT ENAME FROM EMP WHERE ENAME > 'M'; -- → 'M' 보다 사전 순으로 뒤에 오는 이름들 (SMITH, WARD, TURNER, SCOTT …) -- 숫자처럼 크기를 비교하는 게 아니라 '가나다/ABC 순서'로 비교한다 -- ⚠️ 함정 ③ 날짜를 문자열로 비교하면 DB 설정에 의존한다 SELECT ENAME, HIREDATE FROM EMP WHERE HIREDATE >= '1981-01-01'; -- → 실행하는 DB의 날짜 형식(NLS_DATE_FORMAT) 설정에 따라 -- 정상 동작할 수도, ORA-01861 오류가 날 수도 있다 ⚠️ -- ✅ 안전한 방법: TO_DATE 로 명시적 변환 (10강에서 자세히) SELECT ENAME, HIREDATE FROM EMP WHERE HIREDATE >= TO_DATE('1981-01-01','YYYY-MM-DD'); -- ENAME HIREDATE -- ------ ---------- -- ALLEN 1981-02-20 -- WARD 1981-02-22 -- ... -- ⭐ 실무·시험 모두 '날짜는 TO_DATE 로 명시적 변환' 이 원칙이다.
SQL
복사

3. SQL 연산자 4종 ⭐⭐

1) 한눈에 비교

연산자
의미
같은 뜻의 표현
BETWEEN A AND B
A 이상 B 이하 (경계값 포함) ⭐
>= A AND <= B
IN (값1, 값2, …)
목록 중 하나와 일치
= 값1 OR = 값2 OR …
LIKE '패턴'
패턴과 일치 (부분 검색)
—
IS NULL
NULL인지 확인
(= NULL 은 불가!)

2) BETWEEN A AND B — 경계값을 포함한다 ⭐

-- ============================================================ -- 【이해용 예제】 급여가 1000 이상 2000 이하인 사원 -- ============================================================ SELECT ENAME, SAL FROM EMP WHERE SAL BETWEEN 1000 AND 2000; -- 1000과 2000도 '포함' 된다 -- ENAME SAL -- ------ ---- -- ALLEN 1600 -- WARD 1250 -- MARTIN 1250 -- TURNER 1500 -- ADAMS 1100 -- MILLER 1300 → 6건 -- 위와 완전히 똑같은 결과 SELECT ENAME, SAL FROM EMP WHERE SAL >= 1000 -- 이상 AND SAL <= 2000; -- 이하 -- → 동일한 6건
SQL
복사
-- ============================================================ -- 【시험용 예제】 BETWEEN 의 세 가지 함정 ★★ -- ============================================================ -- ⚠️ 함정 ① 순서를 바꾸면 결과가 0건이 된다 SELECT ENAME FROM EMP WHERE SAL BETWEEN 2000 AND 1000; -- → 0건! BETWEEN 은 '작은 값 AND 큰 값' 순서로 써야 한다 -- (내부적으로 SAL >= 2000 AND SAL <= 1000 이 되어 만족하는 행이 없음) -- ⚠️ 함정 ② NOT BETWEEN 은 경계값을 '제외' 한다 SELECT ENAME, SAL FROM EMP WHERE SAL NOT BETWEEN 1000 AND 2000; -- → SAL < 1000 OR SAL > 2000 인 사원 (1000과 2000은 포함되지 않음) -- ENAME SAL -- ------ ----- -- SMITH 800 -- JONES 2975 -- ... → 8건 (14 - 6) -- ⚠️ 함정 ③ 날짜에도 쓸 수 있지만 '시분초'에 주의 -- HIREDATE BETWEEN '81/01/01' AND '81/12/31' 로 쓰면 -- 12월 31일 00시 00분 00초까지만 포함되어, 그날 오후 데이터가 누락될 수 있다
SQL
복사

3) IN — 여러 값 중 하나

-- ============================================================ -- 【이해용 예제】 직무가 CLERK 또는 MANAGER 인 사원 -- ============================================================ SELECT ENAME, JOB FROM EMP WHERE JOB IN ('CLERK', 'MANAGER'); -- 목록 안의 값 중 하나면 통과 -- ENAME JOB -- ------ ------- -- SMITH CLERK -- JONES MANAGER -- BLAKE MANAGER -- CLARK MANAGER -- ADAMS CLERK -- JAMES CLERK -- MILLER CLERK → 7건 -- 위와 완전히 똑같은 결과 (OR 로 풀어 쓴 것) SELECT ENAME, JOB FROM EMP WHERE JOB = 'CLERK' OR JOB = 'MANAGER'; -- → 동일한 7건 -- ⭐ 조건이 많아질수록 IN 이 훨씬 짧고 읽기 좋다
SQL
복사

4) IS NULL — NULL 전용 비교 (06강 회수)

-- ============================================================ -- 【시험용 예제】 NULL은 = 로 비교할 수 없다 ★★ -- ============================================================ -- ❌ 오류는 안 나지만 0건이 나온다 SELECT ENAME, COMM FROM EMP WHERE COMM = NULL; -- → 0건 (COMM = NULL 의 결과가 UNKNOWN 이라 아무 행도 통과 못 함) -- ✅ IS NULL 을 써야 한다 SELECT ENAME, COMM FROM EMP WHERE COMM IS NULL; -- ENAME COMM -- ------ ------ -- SMITH (NULL) -- JONES (NULL) -- ... → 10건 -- ✅ NULL이 아닌 행을 찾을 때는 IS NOT NULL SELECT ENAME, COMM FROM EMP WHERE COMM IS NOT NULL; -- ENAME COMM -- ------ ----- -- ALLEN 300 -- WARD 500 -- MARTIN 1400 -- TURNER 0 ← 0 은 NULL이 아니다! (06강) ⭐ -- → 4건
SQL
복사
⭐ TURNER의 커미션 0은 NULL이 아닙니다."값이 0인 것" 과 "값이 없는 것" 은 완전히 다릅니다. (06강 회수)

4. LIKE 와 와일드카드 ⭐⭐

1) 두 가지 와일드카드

기호
의미
예
매칭되는 것
%
0자 이상의 임의 문자
'S%'
S, SM, SMITH, SCOTT …
_
정확히 1자의 임의 문자
'S_'
SM, SA … (2글자만)
-- ============================================================ -- 【이해용 예제】 LIKE 기본 패턴 3가지 -- ============================================================ -- (1) S 로 시작하는 이름 SELECT ENAME FROM EMP WHERE ENAME LIKE 'S%'; -- ENAME -- ----- -- SMITH -- SCOTT → 2건 -- (2) S 로 끝나는 이름 SELECT ENAME FROM EMP WHERE ENAME LIKE '%S'; -- ENAME -- ----- -- JAMES -- ADAMS → 2건 -- (3) 이름 안에 AR 이 들어가는 사람 SELECT ENAME FROM EMP WHERE ENAME LIKE '%AR%'; -- ENAME -- ------ -- WARD -- MARTIN -- CLARK → 3건
SQL
복사
-- ============================================================ -- 【시험용 예제】 _ 와 % 의 차이를 정확히 구분하기 ★★ -- ============================================================ -- '_A%' : 첫 글자는 아무거나 1자, 둘째 글자가 A, 그 뒤는 자유 SELECT ENAME FROM EMP WHERE ENAME LIKE '_A%'; -- ENAME -- ------ -- WARD ← W-A-R-D : 둘째가 A ✅ -- MARTIN ← M-A-R... : 둘째가 A ✅ -- JAMES ← J-A-M... : 둘째가 A ✅ -- → 3건 -- ⚠️ ALLEN 은 A가 '첫째' 글자이므로 매칭되지 않는다! -- 'A%' 와 비교해 보면 차이가 분명해진다 SELECT ENAME FROM EMP WHERE ENAME LIKE 'A%'; -- ENAME -- ------ -- ALLEN ← 첫 글자가 A ✅ -- ADAMS ← 첫 글자가 A ✅ -- → 2건 -- '__A%' : 셋째 글자가 A SELECT ENAME FROM EMP WHERE ENAME LIKE '__A%'; -- ENAME -- ------ -- BLAKE ← B-L-A-K-E : 셋째가 A ✅ -- CLARK ← C-L-A-R-K : 셋째가 A ✅ -- → 2건 -- -- ⭐ 밑줄(_) 하나가 정확히 한 글자다. 개수를 세는 문제가 자주 출제된다.
SQL
복사

2) ESCAPE — % 나 _ 자체를 찾고 싶을 때 ⭐

문제: "할인율 50% 라는 문자열이 들어간 상품"을 찾으려면? LIKE '%50%%' 라고 쓰면 마지막 %도 와일드카드로 해석되어 원하는 결과가 안 나옵니다.
-- ============================================================ -- 【시험용 예제】 ESCAPE 절로 와일드카드를 '평범한 문자'로 만들기 ★ -- ============================================================ -- 예시 데이터 [PRODUCT] -- 상품코드 상품명 -- -------- ---------------- -- P01 50% 할인상품 -- P02 특가 50000원 -- P03 100% 국산 -- ❌ 그냥 쓰면 % 가 와일드카드로 해석된다 SELECT * FROM PRODUCT WHERE PROD_NM LIKE '%50%%'; -- → P01, P02 둘 다 나옴 (50 이 들어간 모든 것) ⚠️ -- ✅ ESCAPE 로 '탈출 문자'를 지정한다 SELECT * FROM PRODUCT WHERE PROD_NM LIKE '%50\%%' ESCAPE '\'; -- ↑ ↑ -- │ └ 이 % 는 '진짜 퍼센트 문자' (앞에 \ 가 붙었으므로) -- └── ESCAPE 로 지정한 탈출 문자 -- 상품코드 상품명 -- -------- ------------ -- P01 50% 할인상품 → 1건 ✅ -- ⭐ ESCAPE 문자는 아무 글자나 지정할 수 있다 -- ESCAPE '#' 로 지정했다면 '%50#%%' 처럼 쓴다 -- ⭐ 밑줄(_)도 똑같이 탈출시킬 수 있다 : LIKE 'A\_B' ESCAPE '\'
SQL
복사

5. 논리 연산자와 우선순위 ⭐⭐⭐

1) 세 가지 논리 연산자

연산자
의미
통과 조건
AND
그리고
모든 조건이 TRUE
OR
또는
하나라도 TRUE
NOT
부정
조건을 뒤집음

2) ⚠️ AND 가 OR 보다 우선순위가 높다 ⭐⭐⭐

곱셈이 덧셈보다 먼저인 것과 같습니다.2 + 3 * 4 가 2 + 12 이듯이, A OR B AND C 는 A OR (B AND C) 입니다.
-- ============================================================ -- 【시험용 예제】 괄호 하나로 결과가 완전히 달라진다 ★★★ -- 질문: "30번 부서이면서 급여 1500 이상이거나, 직무가 CLERK 인 사원" -- ============================================================ -- (A) 괄호 없음 → AND 가 먼저 묶인다 SELECT ENAME, JOB, DEPTNO, SAL FROM EMP WHERE DEPTNO = 30 AND SAL >= 1500 OR JOB = 'CLERK'; -- 해석: (DEPTNO = 30 AND SAL >= 1500) OR JOB = 'CLERK' -- └────── 30번 부서의 고액자 ──────┘ └ 부서 무관 모든 CLERK ┘ -- ENAME JOB DEPTNO SAL -- ------ -------- ------ ----- -- ALLEN SALESMAN 30 1600 ← 30번 & 1500이상 -- BLAKE MANAGER 30 2850 ← 30번 & 1500이상 -- TURNER SALESMAN 30 1500 ← 30번 & 1500이상 -- SMITH CLERK 20 800 ← CLERK (20번 부서인데도 나옴!) ⚠️ -- ADAMS CLERK 20 1100 ← CLERK -- JAMES CLERK 30 950 ← CLERK -- MILLER CLERK 10 1300 ← CLERK (10번 부서!) → 7건 -- (B) 괄호 있음 → OR 를 먼저 묶는다 SELECT ENAME, JOB, DEPTNO, SAL FROM EMP WHERE DEPTNO = 30 AND (SAL >= 1500 OR JOB = 'CLERK'); -- 해석: 30번 부서인 사람 중에서, 급여 1500 이상이거나 CLERK 인 사람 -- ENAME JOB DEPTNO SAL -- ------ -------- ------ ----- -- ALLEN SALESMAN 30 1600 -- BLAKE MANAGER 30 2850 -- TURNER SALESMAN 30 1500 -- JAMES CLERK 30 950 ← 30번 부서의 CLERK 만 → 4건 -- ⭐ 같은 조건인데 7건 vs 4건! 괄호 하나 차이다. -- ⭐ 실무 원칙: AND 와 OR 를 섞어 쓸 때는 '반드시 괄호를 명시' 한다.
SQL
복사

3) 연산자 우선순위 종합 ⭐

순위
연산자
1
괄호 ( )
2
산술 연산자 * / + -
3
연결 연산자 ||
4
비교 연산자 = <> > < >= <=
5
SQL 연산자 IS NULL LIKE IN BETWEEN
6
NOT
7
AND
8
OR
⭐ 암기 문장: "산술 → 연결 → 비교 → SQL → NOT → AND → OR" 뒤로 갈수록 나중에 계산됩니다. 가장 나중이 OR 라는 것만 확실히 기억하세요.

6. 부정 연산자

긍정
부정
의미
=
<> != ^=
같지 않다
BETWEEN A AND B
NOT BETWEEN A AND B
범위 밖 (경계값 제외)
IN (…)
NOT IN (…)
목록에 없음 ⚠️
LIKE '패턴'
NOT LIKE '패턴'
패턴과 다름
IS NULL
IS NOT NULL
NULL이 아님
-- ============================================================ -- 【이해용 예제】 조건 뒤집기 -- ============================================================ SELECT ENAME, JOB FROM EMP WHERE JOB NOT IN ('CLERK', 'MANAGER'); -- CLERK도 MANAGER도 아닌 사원 -- ENAME JOB -- ------ --------- -- ALLEN SALESMAN -- WARD SALESMAN -- MARTIN SALESMAN -- SCOTT ANALYST -- KING PRESIDENT -- TURNER SALESMAN -- FORD ANALYST → 7건 (14 - 7)
SQL
복사

7. NULL과 WHERE — NOT IN 의 함정 ⭐⭐⭐

🔥 06강에서 미뤄둔 숙제입니다. 원리를 모르면 절대 못 푸는 대표 문제입니다.

1) 현상 — 결과가 무조건 0건이 된다

-- ============================================================ -- 【시험용 예제】 NOT IN 목록에 NULL이 하나라도 있으면? ★★★ -- ============================================================ -- IN 은 정상 동작한다 SELECT ENAME, DEPTNO FROM EMP WHERE DEPTNO IN (10, 20, NULL); -- ENAME DEPTNO -- ------ ------ -- CLARK 10 -- SMITH 20 -- ... → 8건 ✅ (10번 3명 + 20번 5명) -- ❌ NOT IN 은 0건이 된다! SELECT ENAME, DEPTNO FROM EMP WHERE DEPTNO NOT IN (10, 20, NULL); -- → 0건 ⚠️ 30번 부서 사원이 6명이나 있는데도!
SQL
복사

2) 왜 그런가 — 단계별로 풀어보기 ⭐

30번 부서 사원(예: JAMES)을 대입해서 확인해 봅시다
단계
식
결과
①
30 <> 10
TRUE
②
30 <> 20
TRUE
③
30 <> NULL
UNKNOWN ⚠️
종합
TRUE AND TRUE AND UNKNOWN
UNKNOWN
판정
WHERE절 통과?
❌ 탈락
⭐ AND 진리표에서 UNKNOWN이 섞이면TRUE AND UNKNOWN = UNKNOWN (참인지 확신할 수 없으므로) 반면 FALSE AND UNKNOWN = FALSE (이미 거짓이 확정)

3) IN 은 왜 괜찮은가?

연산
전개
NULL의 영향
IN (10, 20, NULL)
=10 **OR** =20 OR =NULL
TRUE OR UNKNOWN = TRUE ✅
NOT IN (10, 20, NULL)
<>10 **AND** <>20 AND <>NULL
TRUE AND UNKNOWN = UNKNOWN ❌
⭐ 차이는 OR 냐 AND 냐입니다.IN은 OR로 풀려서 하나만 TRUE면 통과하지만, NOT IN은 AND로 풀려서 UNKNOWN 하나가 전체를 오염시킵니다.

4) 해결 방법

-- ✅ 방법 ① NULL을 목록에서 제거한다 SELECT ENAME, DEPTNO FROM EMP WHERE DEPTNO NOT IN (10, 20); -- → 30번 부서 6건 정상 조회 ✅ -- ✅ 방법 ② 서브쿼리를 쓸 때는 NULL을 걸러낸다 (15강에서 자세히) SELECT ENAME FROM EMP WHERE EMPNO NOT IN ( SELECT MGR FROM EMP WHERE MGR IS NOT NULL ); -- └─ 이 조건이 없으면 0건! ⚠️ -- (KING 의 MGR 이 NULL 이므로, 안 걸러내면 목록에 NULL이 들어간다)
SQL
복사
⚠️ 실무에서 가장 자주 터지는 버그입니다.NOT IN (서브쿼리) 를 쓸 때는 서브쿼리 결과에 NULL이 없는지 반드시 확인하세요. 이 문제는 15강 서브쿼리에서 다시 만납니다.

8. 출제 포인트 한눈에 정리

#
꼭 외울 것
핵심
1
WHERE절의 통과 기준
TRUE인 행만 (FALSE·UNKNOWN 모두 탈락)
2
같지 않다
<> != ^= 셋 다 동일
3
문자 비교
대소문자 구분, 사전 순으로 비교
4
날짜 비교
문자열 비교는 위험 → TO_DATE 명시적 변환
5
BETWEEN A AND B
경계값 포함, >= A AND <= B 와 동일
6
BETWEEN 순서
작은 값 먼저, 뒤바꾸면 0건
7
NOT BETWEEN
경계값 제외
8
IN (…)
OR 로 풀림
9
% vs _
% = 0자 이상, _ = 정확히 1자 ⭐
10
ESCAPE
% _ 자체를 검색할 때 사용
11
NULL 비교
= NULL ❌ → IS NULL ⭕
12
논리 연산자 우선순위
NOT > AND > OR ⭐
13
전체 우선순위
괄호 → 산술 → 연결 → 비교 → SQL → NOT → AND → OR
14
NOT IN + NULL
무조건 0건 (AND로 풀려 UNKNOWN 전파) ⭐⭐

9. 확인 문제

Q1. WHERE SAL BETWEEN 1000 AND 2000 과 같은 의미의 조건은? ① SAL > 1000 AND SAL < 2000 ② SAL >= 1000 AND SAL <= 2000 ③ SAL >= 1000 OR SAL <= 2000 ④ SAL IN (1000, 2000)
정답 보기
Q2. WHERE SAL BETWEEN 2000 AND 1000 의 결과는?
정답 보기
Q3. EMP 테이블에서 WHERE ENAME LIKE '_A%' 의 결과로 옳은 것은? ① ALLEN, ADAMS ② WARD, MARTIN, JAMES ③ ALLEN, ADAMS, WARD, MARTIN, JAMES ④ CLARK, BLAKE
정답 보기
Q4. 아래 두 SQL의 결과 건수가 다른 이유는?
SQL
결과
(A) WHERE DEPTNO = 30 AND SAL >= 1500 OR JOB = 'CLERK'
7건
(B) WHERE DEPTNO = 30 AND (SAL >= 1500 OR JOB = 'CLERK')
4건
정답 보기
Q5. 논리 연산자의 우선순위를 높은 것부터 나열하시오.
정답 보기