CodeGym /행동 /SQL SELF /데이터 필터링하기 IN 그리고 NOT IN으로

데이터 필터링하기 IN 그리고 NOT IN으로

SQL SELF
레벨 13, 레슨 2
사용 가능

예를 들어, 너가 대학 데이터베이스에서 일하고 있는데, 특정 과목을 듣는 학생들을 찾아야 해. 예를 들어 "프로그래밍", "수학", "물리"를 듣는 학생들 말이야. 물론, 아래처럼 조건문을 길게 쓸 수도 있지:

SELECT *
FROM students 
WHERE course = '프로그래밍'
   OR course = '수학'
   OR course = '물리';

근데 솔직히 이런 식으로 쓰는 거 귀찮고, 별로 멋지지도 않아. 다행히 IN 연산자가 있어서, 똑같은 쿼리를 훨씬 간단하게 쓸 수 있어. 시간도 아끼고:

SELECT *
FROM students 
WHERE course IN ('프로그래밍', '수학', '물리');

진짜 마법 같지? OR 여러 개 쓰는 대신, 그냥 SQL한테 이 리스트 안에 있는 값만 찾아달라고 하면 돼. 만약 값이 아닌 것만 찾고 싶으면 NOT IN을 쓰면 돼 — 이 리스트에 없는 것만 찾아줘 이런 느낌이야.

IN 연산자 문법

IN 연산자 기본 문법은 이래:

SELECT 컬럼들
FROM 테이블
WHERE 컬럼 IN (값1, 값2, 값3, ...);

이제 예제 몇 개 볼까.

예제 1: 여러 과목을 듣는 학생들

예를 들어, students 테이블이 있다고 해보자:

id name course
1 Anna 프로그래밍
2 Mello 물리
3 Kate 수학
4 Dan 화학
5 Olly 생물학

"프로그래밍", "수학", "물리" 듣는 학생들만 찾고 싶으면 IN을 이렇게 써:

SELECT name, course
FROM students
WHERE course IN ('프로그래밍', '수학', '물리');

결과:

name course
Anna 프로그래밍
Mello 물리
Kate 수학

보다시피 IN 연산자 덕분에 훨씬 간단해졌지. OR 여러 개 안 써도 되고, 그냥 관심 있는 값들만 리스트로 넣으면 돼.

예제 2: 특정 과목을 안 듣는 학생들

이번엔 "프로그래밍", "수학", "물리" 안 듣는 학생들만 찾고 싶으면 NOT IN을 써:

SELECT name, course
FROM students
WHERE course NOT IN ('프로그래밍', '수학', '물리');

결과:

name course
Dan 화학
Olly 생물학

이렇게 NOT IN은 course 컬럼 값이 리스트에 없는 모든 행을 반환해.

IN이랑 NOT IN을 서브쿼리랑 같이 쓰기

IN이랑 NOT IN은 두 테이블에서 데이터 비교할 때 진짜 유용해. 예를 들어, 두 개 테이블이 있다고 해보자:

students 테이블:

id name course_id
1 Anna 101
2 Mello 102
3 Kate 103
4 Dan 104

courses 테이블:

id name
101 프로그래밍
102 물리
103 수학
105 화학

이제 courses 테이블에 실제로 존재하는 과목에 등록된 학생만 찾고 싶으면, IN이랑 서브쿼리를 이렇게 써:

SELECT name
FROM students
WHERE course_id IN (
    SELECT id
    FROM courses
);

이 쿼리는 이렇게 동작해: 서브쿼리 SELECT id FROM courses가 모든 과목 id를 반환하고, IN이 course_id가 그 리스트에 있는지 체크해.

결과:

name
Anna
Mello
Kate

Dan이 빠진 이유? Dan의 course_id (104)는 courses 테이블에 없기 때문이야.

NULL 다룰 때 주의할 점

IN 연산자는 중요한 특징이 하나 있어: 값 리스트에 NULL이 있으면 쿼리 결과에 영향을 줄 수 있어. 예제 보자.

grades 테이블:

student_id course_id grade
1 101 A
2 102 NULL
3 103 B

('A', 'B', 'C') 중 하나인 점수를 가진 학생을 찾는 쿼리는 이렇게 쓸 수 있어:

SELECT student_id
FROM grades
WHERE grade IN ('A', 'B', 'C');

결과:

student_id
1
3

grade 컬럼이 NULL인 행은 무시돼. 왜냐면 NULL은 어떤 리스트에도 포함된 걸로 안 치거든.

이번엔 NOT IN을 써보자. 예를 들어:

SELECT student_id
FROM grades
WHERE grade NOT IN ('A', 'B', 'C');

student_id = 2인 행이 나올 거라 기대할 수도 있는데, 결과는 아무것도 없어! 왜냐면 NULL이 리스트의 각 값이랑 비교될 때마다 결과가 항상 미정(UNKNOWN)이기 때문이야. 이거 헷갈릴 수 있으니까, NOT IN 쓸 때 NULL 컬럼이 있으면 꼭 신경 써야 해. 이런 경우엔 NULL 체크를 명시적으로 추가하는 게 좋아:

SELECT student_id
FROM grades
WHERE grade NOT IN ('A', 'B', 'C')
   OR grade IS NULL;

결과:

student_id
2

IN이랑 NOT IN 쓸 때 팁

IN을 써서 SQL 코드 가독성 높이기
컬럼 값이 특정 리스트에 있는지 확인할 때는 OR 여러 개 쓰는 것보다 IN을 쓰는 게 훨씬 좋아.

NOT IN이랑 NULL 조심하기
데이터에 NULL 컬럼이 있으면 예상치 못한 결과가 나올 수 있어. NOT IN 쓸 땐 NULL을 명시적으로 처리해줘.

서브쿼리 성능 높이려면 인덱스 쓰기
IN을 서브쿼리랑 같이 쓸 때, 서브쿼리 컬럼에 인덱스가 있으면 성능 저하를 막을 수 있어.

실전 예제

이번엔 인터넷 쇼핑몰 시스템에서 일한다고 해보자. orders랑 users 테이블이 있어. 한 번도 주문 안 한 유저만 찾고 싶어.

users 테이블:

id name
1 Anna
2 Mello
3 Kate
4 Dan

orders 테이블:

id user_id total
1 1 500
2 3 300

NOT IN으로 문제를 풀어보자:

SELECT name
FROM users
WHERE id NOT IN (
    SELECT user_id
    FROM orders
);

결과:

name
Mello
Dan

이 쿼리는 이렇게 동작해: 먼저 서브쿼리 SELECT user_id FROM orders가 주문한 유저 id(1, 3)를 반환하고, NOT IN이 그 유저들을 빼고 주문 안 한 유저(Mello, Dan)만 남겨줘.

2
과제
SQL SELF, 레벨 13, 레슨 2
잠금
IN을 사용한 행 필터링
IN을 사용한 행 필터링
2
과제
SQL SELF, 레벨 13, 레슨 2
잠금
IN과 서브쿼리를 사용한 필터링
IN과 서브쿼리를 사용한 필터링
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION