데이터베이스 쿼리를 작성할 때 JOIN 연산은 필수적입니다. 이때 필터링 조건을 ON 절에 기술하는지, 혹은 WHERE 절에 기술하는지에 따라 결과 집합이 크게 달라질 수 있습니다. 특히 외부 조인(Outer Join)을 사용할 때 이 차이는 더욱 명확해집니다.
1. 데이터 모델 및 샘플 데이터
비교를 위해 사용자 정보를 담은 두 개의 테이블을 정의합니다.
CREATE TABLE students_a (
name VARCHAR(50),
gender INT,
grade INT
);
CREATE TABLE students_b (
name VARCHAR(50),
gender INT,
grade INT
);
INSERT INTO students_a VALUES ('Kim', 1, 90), ('Lee', 2, 85), ('Park', 1, 70), ('Choi', 2, 60);
INSERT INTO students_b VALUES ('Kim', 1, 95), ('Lee', 2, 80), ('Jung', 1, 75);
2. 동작 방식의 차이
INNER JOIN에서의 동작
내부 조인에서는 두 조건 모두 결과적으로 동일한 교집합을 반환합니다.
-- 방식 1: ON 절에 조건 결합
SELECT * FROM students_a a JOIN students_b b ON a.name = b.name AND a.gender = 1;
-- 방식 2: WHERE 절에 조건 기술
SELECT * FROM students_a a JOIN students_b b ON a.name = b.name WHERE a.gender = 1;
LEFT JOIN에서의 결정적 차이
외부 조인에서는 기준 테이블(왼쪽)의 모든 데이터를 유지해야 합니다. 이때 ON에 조건을 주느냐 WHERE에 주느냐에 따라 결과가 판이하게 달라집니다.
사례: 모든 학생 목록을 조회하되, 조건에 맞는 외부 테이블 데이터가 있으면 표시하고 없으면 NULL로 처리하려는 경우
-- 쿼리 A: ON 절 사용 (기대한 결과)
-- 왼쪽 테이블(a)의 행은 모두 유지되며, ON 조건 만족 시에만 b 데이터가 결합됨
SELECT a.name, b.name AS match_name
FROM students_a a
LEFT JOIN students_b b ON a.name = b.name AND a.gender = 1;
-- 쿼리 B: WHERE 절 사용 (의도하지 않은 결과)
-- 조인 후 생성된 결과 전체에 대해 WHERE 필터가 적용되어 gender가 1이 아닌 행이 모두 삭제됨
SELECT a.name, b.name AS match_name
FROM students_a a
LEFT JOIN students_b b ON a.name = b.name
WHERE a.gender = 1;
요약
- ON 절: 조인 과정에서 대상 행을 선정하는 기준입니다. 외부 조인 사용 시,
ON조건에 실패하더라도 왼쪽 테이블(LEFT JOIN 기준)의 행은 결과에 포함됩니다. - WHERE 절: 조인이 완료되어 생성된 임시 결과 집합 전체를 대상으로 최종 필터링을 수행합니다. 따라서
WHERE조건에 맞지 않는 행은 외부 조인이라 할지라도 최종 결과에서 제외됩니다.