[CS Study] JOIN 2: 외부 조인과 기타 조인 (김영한의 실전 데이터베이스 기본편)
by Mandy's2025. 11. 21.
OUTER JOIN
LEFT OUTER JOIN == LEFT JOIN
RIGHT OUTER JOIN == RIGHT JOIN
조인의 특징
자식에서 부모 조인 : 행의 개수가 그대로 유지가 됨.
FK → PK
주문은 반드시 한 명의 고객에게 속한다.
부모에서 자식 : 행의 개수가 늘어남
PK → FK
부모 테이블의 한 행은 자식 테이블의 여러 행과 매칭될 수 있다.
한 명의 고객이 여러 번 주문할 수 있다.
-- 부모에서 자식 (1행 -> 2행)
select
o.order_id,
o.product_id,
o.user_id as orders_user_id,
u.user_id as users_user_id,
u.name,
u.email
from users u
join orders o on u.user_id = o.user_id
where o.user_id = 1;
실무에서 중요한 이유
조인으로 인해 데이터가 어떻게 변하는지 이해해야 합계, 평균, 개수 같은 집계 함수를 올바르게 사용하고 원하는 분석 결과를 정확하게 도출할 수 있음.
쿼리를 작성하기 전에 항상 어떤 테이블을 기준으로 삼을지, 그리고 조인으로 인해 행 수가 증가하는 상황인지 아닌지, 먼저 생각하는 습관을 들이는 것이 중요하다.
참고: 조인의 유연성
조인의 핵심 원리는 두 테이블의 특정 열의 값이 같은가? - 어떤 열이든 조인 조건으로 쓸 수 있다. (데이터 타입이 같은 경우)
주로 대부분은 pk-fk관계로 사용한다. (데이터의 일관성)
셀프 조인 셀프 조인
동일한 테이블을 두 번 참조하여 조인하는 기법
주로 계층 구조나 상하 관계를 표현할 때 사용 (예: 직원-관리자, 카테고리-상위카테고리)
테이블 별칭(alias)을 반드시 사용해야 구분 가능
하나의 테이블을 자기 자신과 조인하는 기법
select e.name as employee_name, m.name as manager_name from employees e left join employees m on e.manager_id = m.employee_id; -- 김회장님은 상사가 없다 !
크로스 조인
지금까지는 on 이라는 연결고리를 통해 테이블에 이미 존재하는 관계를 찾아내는 작업을 함.
애초에 짝이나 관계가 없는 두 집단을 가지고 가능한 모든 조합을 만들어내려면 어떻게 해야 할까?
insert into 를 사용해서 새로운 테이블을 만들 때 유용하게 사용할 수 있음.
실무에서 치명적인 주의사항
크로스조인은 최대한 사용하지 않는 것이 좋음.
결과의 행수가 기하급수적으로 증가할 수 있음.
참고사항
카테시안 곱이란?
💡 JOIN 조건 없이 여러 테이블이 서로 모든 조합으로 곱해져버리는 상황.
ORM에서 자연스럽게 생기는 이유는:
1:N 또는 N:N 관계를 joinedload(fetch join)로 한 번에 가져오면
내부적으로 JOIN을 하게 된다.
이때 JOIN 결과는 원본 테이블의 row 수 × 자식 row 수가 되어
row가 폭발하게 된다.
예:
Team 100개
Member 50명씩
JOIN FETCH 하면 결과 row는 5000개
→ 이것을 흔히 “카테시안 곱처럼 row가 폭발했다”라고 표현함.
정확한 의미의 “진짜 cross join”은 아니지만,
row 폭발 문제 때문에 현업에서는 “카테시안 곱”이라고 불러버리는 경우가 많다.
ORM에서 매우 흔하게 발생하는 경우
필요한 것만 가져다가 나눠서 크로스 조인을 사용해야 한다.
ORM의 관계 매핑을 사용하는데, 1:N or N:N 관계 매핑이 될 수 있다. (1:1 관계에서는 크게 문제가 되지 않음)
하나의 테이블 기준으로 여러 개의 테이블이 매핑이 되어 있을 때 → 카테시안 곱으로 모든 것을 다 가져온다.
해결방법
selectinload를 사용함.
쿼리를 한 번 더 날리는 것이기 때문에 n+1 ?
패치 조인; n+1문제를 해결하기 위한 전략
lazy loading을 사용함.
데이터의 크기에 맞게 사용을 해야 함.
ORM 은 편하지만 실무에서 사용할 때 주의해야 할 점이 있다!
where 절에서 null 이 포함 되지 않는 경우
where 절
NULL과 비교하면 결과는 TRUE도 FALSE도 아닌 UNKNOWN이 된다. WHERE는 TRUE만 통과시키고, FALSE와 UNKNOWN은 모두 제외한다.
and 표현
AND 자체가 NULL을 포함시키는 게 아니라,
OR 조건 또는 부등호 조건에서 NULL이 의도와 다르게 흘러가는 경우가 많아서 그렇게 느끼는 것