PostgreSQL 교재 · 6편 / 24편

WHERE 절 — BETWEEN·IN·LIKE·NULL

조건 표현 5종과 NULL 3값 논리의 함정. SQL 기초 파트 첫 편.

SQL 기초읽는 시간 7분2026-05-17
WHERE 절의 다양한 비교 연산자들이 도식으로 나열된 일러스트

WHERE 는 SQL 쿼리의 절반 — "어떤 행을 가져올까" 를 결정합니다. 단순 비교(=·>)부터 BETWEEN, IN, LIKE, NULL 까지 정확히 알아두면 쿼리의 8할이 가벼워집니다. 그리고 모든 입문자가 한 번씩 당하는 NULL 3값 논리의 함정도 정리합니다.

비교 연산자 — 6개

연산자의미예시
=같음WHERE id = 5
<> 또는 !=다름WHERE status <> 'paid'
< >크다/작다WHERE age > 18
<= >=이상/이하WHERE price <= 10000
SELECT * FROM users WHERE age >= 19 AND age < 65;
SELECT * FROM users WHERE name <> '관리자';

AND · OR · NOT — 조합

SELECT * FROM orders
WHERE  status = 'paid'
   AND total >= 50000
   AND (region = 'KR' OR region = 'JP')
   AND NOT cancelled;

우선순위: NOT > AND > OR. 헷갈리면 괄호. WHERE a AND b OR cWHERE (a AND b) OR c 와 같습니다. 의도가 (a AND (b OR c)) 면 반드시 괄호.

BETWEEN — 범위 (양 끝 포함)

-- 동일
WHERE age BETWEEN 19 AND 64
WHERE age >= 19 AND age <= 64

-- 부정
WHERE age NOT BETWEEN 19 AND 64

-- 날짜에도
WHERE created_at BETWEEN '2026-01-01' AND '2026-12-31'

날짜 BETWEEN 의 함정. '2026-12-31' 은 시간이 00:00:00 입니다. 12월 31일 오후 데이터가 누락됩니다. 시계열은 created_at >= '2026-01-01' AND created_at < '2027-01-01' 같은 반-개구간이 안전합니다.

IN — "이 중 하나"

WHERE status IN ('pending', 'paid', 'shipped')
WHERE region NOT IN ('CN', 'RU')

-- 서브쿼리도 가능 (10편에서 자세히)
WHERE user_id IN (SELECT id FROM users WHERE active = true)

OR 의 사촌이지만 가독성이 훨씬 좋아요. 5개 이상이면 IN, 2-3개는 OR 가 자연스럽습니다.

LIKE · ILIKE — 패턴 매칭

-- % : 0개 이상의 임의 문자
-- _ : 정확히 1개 문자

WHERE name LIKE '준%'         -- "준" 으로 시작
WHERE name LIKE '%성'         -- "성" 으로 끝
WHERE name LIKE '%박%'        -- "박" 포함

-- ILIKE : 대소문자 무시 (PostgreSQL 확장)
WHERE email ILIKE '%@gmail.com'

-- 와일드카드 자체를 찾고 싶을 때 ESCAPE
WHERE title LIKE '%50\%%' ESCAPE '\'   -- 실제 % 기호 매치

LIKE 와 인덱스. '준%' (앞부분 고정) 은 일반 B-Tree 인덱스가 잘 듣지만, '%성' 이나 '%박%' 는 인덱스를 못 씁니다. 검색이 많으면 trigram 인덱스(pg_trgm) 또는 full-text search 를 16편에서 다룹니다.

IS NULL — NULL 비교의 단 하나의 정답

-- ❌ 안 됨 — NULL 은 어떤 비교에도 NULL 을 반환 (참도 거짓도 아님)
WHERE phone = NULL          -- 항상 빈 결과
WHERE phone <> NULL          -- 항상 빈 결과

-- ✅ 정답
WHERE phone IS NULL
WHERE phone IS NOT NULL

이게 SQL 의 3값 논리(three-valued logic) 입니다 — 결과가 true/false/UNKNOWN(NULL) 세 가지. WHERE 는 true 인 행만 반환하므로 UNKNOWN 은 false 처럼 처리됩니다 — 그래서 phone = NULL 은 항상 빈 결과.

NULL 의 다른 함정들.

· NULL + 1 = NULL. 모든 산술이 NULL 을 만나면 NULL.

· NULL OR true = true (다행). NULL AND true = NULL.

· NOT IN (subquery) 에서 subquery 결과에 NULL 하나만 있으면 전체가 빈 결과. NOT EXISTS 권장.

· COUNT(col) 은 NULL 을 세지 않고, COUNT(*) 만 모든 행을 셉니다.

실전 패턴 — COALESCE 와 NULLIF

-- COALESCE : 첫 NULL 아닌 값
SELECT name, COALESCE(phone, email, '연락처 없음') AS contact
FROM users;

-- NULLIF : 두 값이 같으면 NULL 반환 (DIVISION BY ZERO 방어)
SELECT total / NULLIF(count, 0) AS avg FROM stats;
-- count 가 0 이면 NULL 반환 (에러 안 남)

한 줄 요약 — WHERE 의 체크리스트

  • 같은 값 비교 → = · IN
  • 범위 → >= · < (날짜는 반-개구간, BETWEEN 함정)
  • 패턴 → LIKE / ILIKE (앞 와일드카드 = 인덱스 못 씀)
  • NULL → 항상 IS NULL / IS NOT NULL
  • NULL 산술 → COALESCE 로 기본값
  • 0 나눗셈 → NULLIF(x, 0)

7편 — ORDER BY·LIMIT·OFFSET

정렬과 페이지네이션, 그리고 OFFSET 만 쓰면 왜 느려지는지(keyset pagination).

📚 PostgreSQL 배우기 교재
이전: 5편 CRUD · 현재: 6편 (SQL 기초) · 다음 → 7편 ORDER BY · 진행: 6/24

© 2026 주나이테크(주) @JUNAITECH