회원 20명 전부 말고,
WHERE — 행을 거르는 필터
3-1에서 SELECT로 행을 전부 꺼내봤죠. 이번엔 "30세 이상만", "이름에 크림이 들어간 상품만" — 조건에 맞는 행만 남깁니다. 비교 연산자부터 BETWEEN·IN·LIKE·NULL 함정·AND/OR까지, 행을 거르는 도구 전부를 한 번에 손에 쥡니다.
이번 섹션의 여정
완료 ✓
지금 여기
ORDER BY · GROUP BY · HAVING
JOIN ⭐ · CASE/서브쿼리
강의 메인
WHERE — 한 마디로 끝납니다
3-1에서 SELECT * FROM members; 로 회원 20명을 전부 꺼내봤습니다. 근데 실무 질문은 대부분 이렇죠 — “전부 말고, 30세 이상인 사람만 보고 싶은데요?” 이런 조건이 필요할 때 쓰는 게 WHERE 입니다.
WHERE 는 행을 거르는 필터입니다. 그 한 마디예요. SELECT 가 꺼내고, WHERE 가 거릅니다.
SELECT
[컬럼]
FROM
[테이블]
WHERE
[조건];SELECT 문 뒤에 WHERE [조건] 한 절만 붙이면 됩니다. 바로 첫 필터를 쳐볼게요 — “members 중에서, 나이가 30 이상인 사람만.”
SELECT
*
FROM
members
WHERE
age >= 30;| member_id | member_name | gender | age | joined_at |
|---|---|---|---|---|
| 1 | 김철수 | M | 35 | 2025-01-15 |
| 3 | 박민수 | M | 42 | 2025-02-10 |
| 4 | 정수진 | F | 31 | 2025-03-05 |
| 6 | 강서연 | F | 38 | 2025-04-12 |
| ⋮ | ||||
비교 연산자는 평소 알던 그대로예요.
| 연산자 | 의미 |
|---|---|
= | 같다 — 한 개 (== 아님) |
!= 또는 <> | 다르다 (둘 다 동작, 같은 의미) |
< > | 미만 / 초과 |
<= >= | 이하 / 이상 |
프로그래밍 언어의 == 습관 때문에 누구나 한 번은 틀립니다. SQL 에서 같다는 = 한 개 — == 를 치면 바로 문법 에러예요. “다르다”는 != 와 <> 둘 다 되는데, 이 강의에서는 != 로 통일합니다.
범위는 BETWEEN, 목록은 IN
자주 쓰는 조건 패턴 두 가지를 바로 이어갑니다. 먼저 범위 — “나이 25에서 35 사이.”
SELECT
member_name,
age
FROM
members
WHERE
age BETWEEN 25 AND 35;age >= 25 AND age <= 35 와 같은 의미인데 훨씬 깔끔하죠. 한 가지만 기억하세요 — 양쪽 끝 값도 포함입니다.
| member_name | age |
|---|---|
| 김철수 | 35 |
| 이영희 | 28 |
| 정수진 | 31 |
| 최지훈 | 25 |
| ⋮ | |
다음은 목록 — “카테고리가 1 또는 2인 상품.” 여러 값 중 하나에만 맞으면 통과시키는 IN 입니다.
SELECT
*
FROM
products
WHERE
category_id IN (1, 2);의류 8개 + 전자기기 7개 = 15행이 나옵니다. OR 를 나열한 것과 같은 의미인데, 차이를 보세요.
category_id = 1 OR category_id = 2 OR …
값이 늘어날수록 한없이 길어지고, 하나만 빠뜨려도 결과가 조용히 달라집니다. 읽는 사람도 의도를 한눈에 파악하기 어려워요.
category_id IN (1, 2, 5)
“이 목록 중 하나면 통과.” 의류·전자기기·뷰티 — 19행이 한 줄로 끝납니다. 값이 많을수록 IN 이 빛나요.
패턴 검색 — LIKE 와 와일드카드 %
이번엔 문자열입니다. 상품 이름을 정확히 다 알 때는 = 로 찾으면 되지만, “이름에 ‘크림’이 들어간 상품” 처럼 일부만 가지고 찾을 때는 LIKE 를 씁니다.
SELECT
*
FROM
products
WHERE
product_name LIKE '%크림%';| product_id | product_name | price | category_id |
|---|---|---|---|
| 27 | 수분 크림 | 32000 | 5 |
% 가 와일드카드 — “어떤 문자든, 몇 개든 OK” 라는 뜻입니다. 그래서 % 를 어디에 붙이느냐가 핵심이에요. 우리 shop DB 에서 직접 돌려보면 차이가 분명합니다.
| 패턴 | 의미 | shop DB 실행 결과 |
|---|---|---|
'크림%' | ”크림”으로 시작 | 0행 — 크림으로 시작하는 상품이 없음 |
'%크림' | ”크림”으로 끝 | 1행 — 수분 크림 |
'%크림%' | 어디든 포함 | 1행 — 수분 크림 |
같은 단어 “크림”인데 % 위치만 바꿨더니 결과가 달라졌죠. 의도한 위치에 정확히
붙이세요. 다른 단어로도 바로 실험해볼 수 있습니다 — '%무선%' 은 무선
이어폰·무선 마우스 2행, '유기농%' 은 유기농 견과류·유기농 꿀 2행.
NULL 함정 — = 로는 절대 못 잡습니다
여기서 한 가지, 반드시 외워야 할 함정이 나옵니다. NULL 은 “값이 없다” 라는 특수 상태예요. 0도 아니고 빈 문자열도 아니고 — 존재하지 않음. 그래서 NULL 과 비교할 때 = 를 쓰면 절대 안 됩니다.
WHERE age = NULL
에러도 안 납니다. 그냥 조용히 빈 결과만 돌아와요. NULL 은 “값이 없음”이라, = 로 비교하는 순간 그 비교 자체가 성립하지 않습니다 — 데이터가 어떻든 항상 0행.
WHERE age IS NULL
NULL 인지 묻는 전용 문법이 따로 있습니다. 반대는 IS NOT NULL. NULL 비교는 오직 이 둘 — 외우세요.
-- ❌ 잘못 — 에러도 없이, 결과가 항상 0행
SELECT
*
FROM
members
WHERE
age = NULL;
-- ✅ 올바름 — NULL 전용 문법
SELECT
*
FROM
members
WHERE
age IS NULL;
SELECT
*
FROM
members
WHERE
age IS NOT NULL;init.sql 의 모든 컬럼이 NOT NULL 이라, 위 쿼리는 지금 둘 다 0행이에요. 하지만
차이는 분명합니다 — = NULL 은 데이터와 무관하게 항상 0행인 함정이고, IS NULL 은 NULL 이 생기는 순간 정확히 잡아냅니다. 실무 DB 에서는 NULL 을 반드시
만나요 — 6-3에서 본격적으로 다룹니다.
AI 가 만든 SQL 도 NULL 처리에서 자주 실수합니다. WHERE 절에 = NULL 이
보이면 무조건 의심하세요 — 에러 없이 빈 결과만 나오는, SQL 에서 가장 조용한
버그입니다. 섹션 6의 검증 체크리스트에도 1순위로 올라가요.
조건 결합 — AND · OR · NOT, 그리고 괄호
조건을 여러 개 묶을 차례입니다. 세 가지뿐이에요.
AND — 둘 다 참일 때만 통과. “여성이고, 나이 30 이상.”
SELECT
*
FROM
members
WHERE
gender = 'F' AND age >= 30;OR — 둘 중 하나만 참이면 통과. “도서 카테고리이거나, 가격이 5만원 이상.”
SELECT
*
FROM
products
WHERE
category_id = 4 OR price >= 50000;NOT — 부정. “남성이 아닌 회원.”
SELECT
*
FROM
members
WHERE
NOT gender = 'M';
-- 같은 의미, 더 자연스럽게:
SELECT
*
FROM
members
WHERE
gender != 'M';그리고 제일 중요한 것 하나 — AND 와 OR 를 같이 쓸 땐 괄호를 꼭 치세요. AND 가 OR 보다 우선순위가 높아서, 괄호 없이 섞으면 의도와 완전히 다른 결과가 나옵니다. “남녀 불문, 40세 이상 회원” 을 뽑으려던 의도였다고 해볼게요.
AND 가 먼저 묶여버립니다
gender = ‘F’ OR gender = ‘M’ AND age >= 40 은 “여성이거나, (남성이고 40 이상)” 으로 읽힙니다. 여성 10명이 나이와 무관하게 전부 통과 — 의도와 전혀 다른 13행이 나와요.
(F 또는 M) 이고 40 이상
(gender = ‘F’ OR gender = ‘M’) AND age >= 40 — 의도대로 40세 이상 회원 5명만 나옵니다. 괄호가 의도를 고정해요.
복합 조건은 항상 이렇게 — 괄호로 의도를 명확히.
-- "여성 30세 이상" 이거나 "45세 이상"
SELECT
*
FROM
members
WHERE
(gender = 'F' AND age >= 30)
OR age >= 45;여성 30세 이상 6명에 45세 이상인 조성민(45)·권현석(50)이 더해져 8행. 괄호 덕에 쿼리만 봐도 의도가 그대로 읽히죠.
AND/OR 우선순위 함정은 AI 가 만든 SQL 에서도 종종 나오는 실수예요. WHERE 절에 AND 와 OR 가 같이 보이는데 괄호가 없다면 — 결과 행 수가 의도와 맞는지 꼭 확인하세요.
한눈에 정리
WHERE 는 행을 거르는 필터. 그 한 마디에 오늘 배운 도구 전부가 담깁니다.
| 키워드 | 용도 | 예시 |
|---|---|---|
= != < > <= >= | 비교 — = 는 한 개 | age >= 30 |
BETWEEN a AND b | 범위 — 양끝 포함 | age BETWEEN 25 AND 35 |
IN (...) | 목록 중 하나 | category_id IN (1, 2, 5) |
LIKE '%...%' | 패턴 — % 위치가 핵심 | product_name LIKE '%크림%' |
IS NULL / IS NOT NULL | NULL 처리 ⚠️ | age IS NULL |
AND OR NOT | 조건 결합 — 괄호로 묶기 | (A AND B) OR C |
SELECT 가 꺼내고, WHERE 가 거른다. 이제 20행 전체가 아니라 딱 원하는
행만 남길 수 있습니다. 특히 = NULL 함정과 괄호 — 이 둘은 AI 가 만든 SQL 을
검증할 때도 1순위 체크포인트예요.
자주 막히는 지점
SQL 에서 가장 조용한 함정입니다 — 문법 에러가 아니라서, 빈 결과만 돌아오고 아무도 알려주지 않아요.
IS NULL / IS NOT NULL 로 바꾸세요. NULL 은 = 로 비교할 수 없습니다.프로그래밍 언어 습관 때문에 누구나 한 번은 겪습니다. 에러 메시지의 near
부분에 == 가 보이면 바로 이 케이스예요.
= 한 개. == 는 SQL 에 없습니다.‘크림%’ 는 “크림으로 시작”만 찾습니다. 우리 DB 의 수분 크림은
크림으로 시작하지 않아서 0행이에요.
% 위치부터 확인 — 포함 검색이면 '%단어%' 처럼 양쪽에 붙입니다.필터까지 손에 익었으면 다음 궁금증은 자연스럽게 이거죠 — “거른 결과를 정렬하고 싶다, 상위 5개만 보고 싶다.” 그게 다음 강의 ORDER BY / LIMIT 입니다. 그 전에, 연습 문제로 WHERE 를 손에 붙이고 가요.