2025-08-18 23:44
Tags:
SQL WHERE 절 완벽 핸드북 데이터베이스의 마법 필터, 원하는 데이터만 골라내는 기술
데이터는 현대 시대의 원유라고 불립니다. 하지만 정제되지 않은 원유가 쓸모없듯, 방대한 데이터 더미 역시 그 자체로는 가치가 없습니다. 우리가 원하는 것은 그 속에서 의미 있는 정보를 ‘찾아내는’ 능력입니다. SQL(Structured Query Language)은 바로 이 ‘찾아내는’ 능력을 우리에게 부여하는 언어이며, 그 중심에는 WHERE
절이 있습니다.
WHERE
절은 데이터베이스라는 거대한 도서관에서 우리가 원하는 책만 정확히 찾아주는 똑똑한 사서와 같습니다. 이 글을 통해 여러분은 WHERE
라는 사서를 자유자재로 부리며, 수백만, 수천만 건의 데이터 속에서도 단 몇 초 만에 원하는 정보를 정확히 추출하는 데이터 전문가로 거듭나게 될 것입니다.
1. WHERE
절은 왜 만들어졌을까? (탄생 배경)
초창기 데이터베이스 시스템은 단순히 데이터를 저장하고, 저장된 모든 것을 그대로 불러오는 기능에 초점을 맞췄습니다. 하지만 데이터가 기하급수적으로 쌓이기 시작하면서 새로운 문제가 발생했습니다.
“전체 직원 목록이 아니라, ‘서울’에 사는 직원만 보고 싶은데?” “모든 제품 정보가 아니라, 재고가 10개 미만인 제품만 확인하고 싶은데?” “모든 고객이 아니라, 지난달에 10만 원 이상 구매한 VIP 고객 명단이 필요한데?”
이러한 요구사항들은 ‘전체 데이터’가 아닌 **‘특정 조건을 만족하는 일부 데이터’**를 선별해야 할 필요성을 명확히 보여주었습니다. 단순히 모든 데이터를 가져와서 애플리케이션(예: 엑셀, 프로그래밍 코드)에서 일일이 필터링하는 방식은 데이터 양이 많아질수록 비효율적이고 느려졌습니다.
이 문제를 해결하기 위해 탄생한 것이 바로 WHERE
절입니다. WHERE
는 데이터베이스 시스템 자체에 필터링 조건을 ‘요청’하는 역할을 합니다. 즉, 불필요한 데이터를 처음부터 가져오지 않고, 데이터베이스 서버가 직접 조건을 검사하여 결과만 전달해주도록 만드는 것입니다. 이는 네트워크 트래픽을 줄이고, 애플리케이션의 부담을 덜어주며, 데이터 처리 속도를 획기적으로 개선하는 결과를 가져왔습니다.
비유: 온라인 쇼핑몰에서 수만 개의 상품을 모두 본 다음, 컴퓨터 앞에서 원하는 상품을 하나씩 찾는 것과, ‘가격: 1만 원 이하’, ‘색상: 검은색’ 필터를 걸어 원하는 상품 목록만 보는 것의 차이와 같습니다. WHERE
는 바로 이 ‘필터’ 역할을 수행합니다.
2. WHERE
절의 기본 구조와 문법
WHERE
절의 구조는 매우 직관적이고 간단합니다. SELECT
문으로 어떤 컬럼을 가져올지, FROM
문으로 어떤 테이블에서 가져올지 지정한 다음, WHERE
키워드 뒤에 원하는 ‘조건’을 명시하면 됩니다.
SELECT column1, column2, ...
FROM table_name
WHERE [조건];
-
SELECT column1, column2, ...
: 조회하고 싶은 데이터의 열(컬럼)을 지정합니다. -
FROM table_name
: 데이터를 가져올 테이블을 지정합니다. -
WHERE [조건]
: 데이터를 필터링할 조건을 명시합니다. 이 조건이 참(True)으로 평가되는 행(row)들만 결과에 포함됩니다.
예를 들어, Employees
라는 테이블에서 City
가 ‘Seoul’인 직원의 이름(FirstName
)과 직급(Title
)을 조회하고 싶다면 다음과 같이 작성합니다.
SELECT FirstName, Title
FROM Employees
WHERE City = 'Seoul';
이 쿼리는 Employees
테이블의 모든 행을 하나씩 살펴보면서, City
컬럼의 값이 ‘Seoul’과 일치하는지 검사합니다. 그리고 일치하는 행의 FirstName
과 Title
값만 우리에게 보여줍니다.
3. WHERE
절의 핵심 무기: 연산자(Operators)
WHERE
절의 진정한 힘은 다양한 ‘연산자’를 통해 복잡하고 세밀한 조건을 만들 수 있다는 점에서 나옵니다. 연산자는 조건을 만드는 데 사용되는 기호나 키워드입니다.
3.1. 비교 연산자 (Comparison Operators)
가장 기본적이고 많이 사용되는 연산자입니다. 두 값을 비교하여 참 또는 거짓을 반환합니다.
연산자 | 설명 | 예시 |
= | 같다 | WHERE City = 'London' (도시가 London인 경우) |
<> 또는 != | 같지 않다 | WHERE City <> 'London' (도시가 London이 아닌 경우) |
> | 크다 | WHERE Salary > 50000 (급여가 50000을 초과하는 경우) |
< | 작다 | WHERE Stock < 10 (재고가 10 미만인 경우) |
>= | 크거나 같다 | WHERE Age >= 30 (나이가 30세 이상인 경우) |
<= | 작거나 같다 | WHERE Price <= 100 (가격이 100 이하인 경우) |
주의: 문자열 값을 비교할 때는 작은따옴표('
)로 감싸야 합니다. (City = 'Seoul'
) 숫자 값은 그대로 사용합니다. (Age = 30
)
3.2. 논리 연산자 (Logical Operators)
두 개 이상의 조건을 결합하여 더 정교한 필터링을 가능하게 합니다.
-
AND
: 두 조건이 모두 참일 때만 전체 조건이 참이 됩니다.-
예시: ‘Sales’ 부서에 속해 있으면서(AND) 급여가 60000 이상인 직원을 찾고 싶을 때
SELECT * FROM Employees WHERE Department = 'Sales' AND Salary >= 60000;
-
-
OR
: 두 조건 중 하나라도 참이면 전체 조건이 참이 됩니다.-
예시: 도시가 ‘Seoul’이거나(OR) ‘Busan’인 직원을 모두 찾고 싶을 때
SELECT * FROM Employees WHERE City = 'Seoul' OR City = 'Busan';
-
-
NOT
: 조건의 결과를 반대로 뒤집습니다. 참은 거짓으로, 거짓은 참으로 만듭니다.-
예시: 부서가 ‘HR’이 아닌 모든 직원을 찾고 싶을 때
SELECT * FROM Employees WHERE NOT Department = 'HR';
-
3.3. 특수 연산자 (Specialized Operators)
특정 상황에서 매우 유용하게 사용되는 연산자들입니다.
-
BETWEEN ... AND ...
: 특정 범위 내에 있는 값을 찾습니다. 시작값과 끝값을 모두 포함합니다.-
예시: 급여가 50000에서 70000 사이인 직원을 찾고 싶을 때
SELECT * FROM Employees WHERE Salary BETWEEN 50000 AND 70000; -- 위 쿼리는 아래와 동일합니다. -- WHERE Salary >= 50000 AND Salary <= 70000;
-
-
IN (...)
: 목록에 포함된 값 중 하나와 일치하는 데이터를 찾습니다.OR
를 여러 번 사용하는 것보다 간결하고 효율적입니다.-
예시: 도시가 ‘Seoul’, ‘Busan’, ‘Incheon’ 중 하나인 직원을 찾고 싶을 때
SELECT * FROM Employees WHERE City IN ('Seoul', 'Busan', 'Incheon'); -- 위 쿼리는 아래와 동일합니다. -- WHERE City = 'Seoul' OR City = 'Busan' OR City = 'Incheon';
-
-
LIKE
: 문자열의 일부가 일치하는 데이터를 찾을 때, 즉 패턴 매칭에 사용됩니다. 와일드카드 문자와 함께 사용됩니다.-
%
(퍼센트): 0개 이상의 모든 문자를 의미합니다. -
_
(언더스코어): 정확히 1개의 문자를 의미합니다. -
예시 1: 성(LastName)이 ‘Kim’으로 시작하는 모든 직원을 찾고 싶을 때
SELECT * FROM Employees WHERE LastName LIKE 'Kim%';
-
예시 2: 이름(FirstName)에 ‘a’가 포함된 모든 직원을 찾고 싶을 때
SELECT * FROM Employees WHERE FirstName LIKE '%a%';
-
예시 3: 이름이 4글자이고 ‘J’로 시작하며 ‘n’으로 끝나는 직원을 찾고 싶을 때 (예: John)
SELECT * FROM Employees WHERE FirstName LIKE 'J__n';
-
-
IS NULL
/IS NOT NULL
: 값이 없는, 즉NULL
인 데이터를 찾거나,NULL
이 아닌 데이터를 찾을 때 사용합니다.-
매우 중요:
NULL
은 ‘값이 없음’을 의미하는 특별한 상태이므로,= NULL
이나<> NULL
과 같은 비교 연산자로는 비교할 수 없습니다. 반드시IS NULL
또는IS NOT NULL
을 사용해야 합니다. -
예시: 보너스(Bonus)를 받지 않은 (Bonus 컬럼이 NULL인) 직원을 찾고 싶을 때
SELECT * FROM Employees WHERE Bonus IS NULL;
-
4. WHERE
절 심화 학습: 전문가의 길
기본적인 연산자에 익숙해졌다면, 이제 WHERE
절을 더욱 강력하게 만들어주는 몇 가지 심화 개념을 알아볼 차례입니다.
4.1. 연산자 우선순위와 괄호 ()
여러 논리 연산자를 함께 사용할 때, SQL은 정해진 우선순위에 따라 연산을 처리합니다. 일반적으로 NOT
→ AND
→ OR
순서로 처리됩니다.
예를 들어, 다음 쿼리를 봅시다. WHERE Department = 'Sales' OR Department = 'Marketing' AND Salary > 70000
이 쿼리는 우리가 의도한 대로 “Sales 부서 직원이거나, Marketing 부서이면서 급여가 70000 초과인 직원”을 찾아줄까요? 아닙니다. AND
가 OR
보다 우선순위가 높기 때문에, SQL은 Department = 'Marketing' AND Salary > 70000
을 먼저 계산합니다. 즉, “Marketing 부서이면서 급여 70000 초과인 직원” 또는 “Sales 부서 직원”을 찾게 됩니다.
우리가 원하는 대로 “Sales 또는 Marketing 부서에 속한 직원들 중에서, 급여가 70000을 초과하는 사람”을 찾으려면 **괄호 ()
**를 사용해 우선순위를 명시적으로 지정해야 합니다.
SELECT * FROM Employees
WHERE (Department = 'Sales' OR Department = 'Marketing') AND Salary > 70000;
괄호는 수학에서와 마찬가지로, 가장 먼저 계산되어야 할 부분을 묶어주는 역할을 합니다. 복잡한 조건을 작성할 때는 괄호를 적극적으로 사용하여 논리적 오류를 방지하는 것이 매우 중요합니다.
4.2. WHERE
절과 서브쿼리(Subquery)
WHERE
절의 조건 값으로 또 다른 SELECT
쿼리의 결과를 사용할 수 있습니다. 이를 서브쿼리라고 합니다. 서브쿼리는 쿼리를 더욱 동적으로 만들어줍니다.
- 예시: ‘UK’에 위치한 공급업체(Suppliers)가 공급하는 모든 제품(Products) 목록을 찾고 싶을 때
먼저 ‘UK’에 있는 공급업체의 ID를 찾고, 그 ID를 IN
연산자와 함께 사용합니다.
SELECT ProductName
FROM Products
WHERE SupplierID IN (SELECT SupplierID FROM Suppliers WHERE Country = 'UK');
안쪽의 (SELECT SupplierID FROM Suppliers WHERE Country = 'UK')
쿼리가 먼저 실행되어 ‘UK’ 공급업체 ID 목록 (예: 1, 5, 12)을 반환합니다. 그러면 바깥쪽 쿼리는 WHERE SupplierID IN (1, 5, 12)
와 동일하게 동작하여 해당 제품들을 찾아냅니다.
4.3. WHERE
vs HAVING
: 결정적 차이
WHERE
와 비슷하게 그룹화된 데이터를 필터링하는 HAVING
절이 있습니다. 둘의 차이를 이해하는 것은 중급 SQL 사용자로 나아가는 중요한 단계입니다.
-
WHERE
: 그룹화(GROUP BY) 하기 전의 개별 행들을 필터링합니다. -
HAVING
: 그룹화(GROUP BY) 한 후의 결과 그룹들을 필터링합니다. 집계 함수(e.g.,COUNT()
,SUM()
,AVG()
)에 대한 조건을 지정할 때 사용됩니다. -
예시: 주문(Orders)이 5건 이상인 고객(CustomerID)만 찾고 싶을 때
잘못된 사용 (WHERE): WHERE
절에서는 집계 함수를 사용할 수 없습니다.
-- 이 쿼리는 에러를 발생시킵니다.
SELECT CustomerID, COUNT(OrderID)
FROM Orders
WHERE COUNT(OrderID) >= 5 -- WHERE 절에는 집계 함수를 쓸 수 없음
GROUP BY CustomerID;
올바른 사용 (HAVING):
SELECT CustomerID, COUNT(OrderID) AS OrderCount
FROM Orders
GROUP BY CustomerID
HAVING COUNT(OrderID) >= 5; -- 그룹화된 결과에 대해 필터링
이 쿼리는 먼저 GROUP BY CustomerID
를 통해 고객별로 주문을 그룹화하고 각 그룹의 주문 수를 셉니다. 그런 다음, HAVING
절이 주문 수가 5 이상인 그룹만 남겨서 최종 결과를 보여줍니다.
5. 결론: WHERE
는 데이터 탐험의 나침반
WHERE
절은 단순히 SQL 문법의 일부가 아닙니다. 그것은 방대한 데이터의 바다를 항해하는 탐험가에게 주어진 가장 강력한 나침반입니다. WHERE
를 통해 우리는 불필요한 정보의 홍수 속에서 길을 잃지 않고, 비즈니스 질문에 대한 답, 숨겨진 인사이트, 그리고 중요한 의사결정의 근거가 되는 핵심 데이터를 정확하게 찾아낼 수 있습니다.
오늘 배운 다양한 연산자와 기법들을 꾸준히 연습하여 여러분의 ‘데이터 사서’를 능숙하게 훈련시키십시오. WHERE
절을 마스터하는 순간, 여러분은 단순한 데이터 소비자를 넘어, 데이터를 통해 가치를 창출하는 진정한 데이터 전문가의 길에 들어서게 될 것입니다.