논리적 joins #
논리적 join은 다시 아래의 네 가지로 나뉘어집니다. 오늘은 이 중에서 Outer Join에 대해 알아보겠습니다.
Outer Join #
외부조인은 두 테이블을 결합해 하나의 조인된 결과를 반환합니다.
두 테이블이 조인 될 때, 일치하지 않는 값도 포함합니다. 일치하지 않아 값이 존재하지 않는 경우 NULL을 채워 넣습니다.
외부 조인: Outer join #
외부조인의 특징
- 외부 조인은 두 테이블을 결합할 때, 일치하는 행이 없는 경우에도 한쪽 테이블의 데이터를 포함합니다.
외부 조인은 세 가지로 나뉘어집니다.
- 외부조인
- 왼쪽 외부 조인 (Left Outer Join)
- 오른쪽 외부 조인 (Right Outer Join)
- 전체 외부 조인 (Full Outer Join)
왼쪽과 오른쪽에 대해 #
외부조인을 알아보기 앞서 왼쪽, 오른쪽 테이블에 대해서 알아두어야만 합니다. 왼쪽, 오른쪽은 각각 왼쪽 테이블, 오른쪽 테이블로 테이블을 가리키며 각 테이블의 join시의 역할을 나타냅니다.
- 왼쪽: 왼쪽은 SQL 쿼리 구문에서 LEFT JOIN 키워드 바로 앞에 위치하는 테이블을 가리킵니다.
- 예를 들어 아래 쿼리에선
LEFT OUTER JOIN
앞의 테이블인 직원이 왼쪽입니다.
SELECT * FROM 직원 LEFT OUTER JOIN 부서 ON 직원.부서ID = 부서.부서ID;
- 예를 들어 아래 쿼리에선
- 오른쪽: 위의 예에서 바로 알 수 있듯이 부서 테이블이 오른쪽 테이블이 됩니다.
왼쪽 외부 조인 (Left Outer Join) #
- 왼쪽 외부 조인은 왼쪽 테이블의 모든 행은 조인 결과에 포함됩니다.
- 오른쪽 테이블과 일치하는 행이 없을 경우 NULL로 채워집니다.
예시 #
직원(employees)과 부서(departments) 테이블을 가정해 보겠습니다.
- 왼쪽 테이블의 모든 행은 조인 결과에 포함됩니다.
- 오른쪽 테이블에 일치하는 행이 없다면 NULL로 채워집니다.
직원 테이블 (왼쪽 테이블)
직원ID | 이름 | 부서ID |
---|---|---|
1 | 홍길동 | 101 |
2 | 이순신 | 102 |
3 | 강감찬 | 103 |
4 | 장보고 | NULL |
부서 테이블 (오른쪽 테이블)
부서ID | 부서명 |
---|---|
101 | 개발 |
102 | 마케팅 |
104 | 인사 |
위의 두 테이블에 대해 아래의 query를 실행해보겠습니다.
SELECT 직원.직원ID, 직원.이름, 부서.부서명
FROM 직원
LEFT OUTER JOIN 부서 ON 직원.부서ID = 부서.부서ID;
쿼리의 결과를 예측해볼 수 있습니다.
- 홍길동, 이순신은 부서 테이블에도 부서ID가 존재하므로 확실히 SELECT 한 모든 값이 정상적으로 나올 것입니다.
- 강감찬, 장보고의 부서ID는 부서 테이블에 존재하지 않으므로 부서명에서 NULL이 나올 것입니다.
조인 결과
직원ID | 이름 | 부서명 |
---|---|---|
1 | 홍길동 | 개발 |
2 | 이순신 | 마케팅 |
3 | 강감찬 | NULL |
4 | 장보고 | NULL |
오른쪽 외부 조인: (Right Outer Join) #
오른쪽 외부 조인은 왼쪽 외부 조인에서 오른쪽 테이블의 모든 행을 결과에 포함시킵니다.
내용 자체는 왼쪽 외부 조인과 같으므로 생략 가능합니다.
예시 #
직원 테이블 (왼쪽 테이블)
직원ID | 이름 | 부서ID |
---|---|---|
1 | 홍길동 | 101 |
2 | 이순신 | 102 |
3 | 강감찬 | 103 |
4 | 장보고 | NULL |
부서 테이블 (오른쪽 테이블)
부서ID | 부서명 |
---|---|
101 | 개발 |
102 | 마케팅 |
104 | 인사 |
SELECT 직원.직원ID, 직원.이름, 부서.부서명
FROM 부서
RIGHT OUTER JOIN 직원 ON 직원.부서ID = 부서.부서ID;
오른쪽 외부 조인이므로 아래의 조건을 만족시켜야 합니다.
- 부서 테이블의 모든 튜플은 조인 결과에 포함되어야 합니다.
이 조건을 지키기 위해서 가장 쉬운 방법은 먼저 부서 테이블을 조인 결과에 모두 추가해놓는 것이 가장 합리적일 것입니다.
실제 조인 결과도 그런지 확인하겠습니다.
조인 결과
직원ID | 이름 | 부서명 |
---|---|---|
1 | 홍길동 | 개발 |
2 | 이순신 | 마케팅 |
NULL | NULL | 인사 |
3 | 강감찬 | NULL |
4 | 장보고 | NULL |
- 조인 결과의 상위 3개의 튜플을 확인하면 개발, 마케팅, 인사 순으로
부서 테이블의 부서명 정렬순서를 따릅니다.
- 부서명이 인사인 경우가 왼쪽 테이블에 없으므로 NULL로 채워졌습니다.
오른쪽 테이블이 모두 소진되었으므로 왼쪽 테이블의 남은 값들을 입력해주면 됩니다.
전체 외부 조인 (Full Outer Join) #
전체 외부 조인은 왼쪽, 오른쪽 조인의 조건을 왼쪽, 오른쪽에 모두 적용하는 것입니다.
- 왼쪽, 오른쪽 테이블의 모든 행을 포함합니다.
- 일치하는 행이 없는 경우 NULL을 채워 넣습니다.
- 일치하지 않는 행 = 한 테이블에는 존재하나, 다른 테이블엔 존재하지 않는 행을 의미함
예시 #
바로 예시를 확인하겠습니다.
직원 테이블 (왼쪽 테이블)
직원ID | 이름 | 부서ID |
---|---|---|
1 | 홍길동 | 101 |
2 | 이순신 | 102 |
3 | 강감찬 | 103 |
4 | 장보고 | NULL |
부서 테이블 (오른쪽 테이블)
부서ID | 부서명 |
---|---|
101 | 개발 |
102 | 마케팅 |
104 | 인사 |
아래의 query를 실행하면 어떤 결과를 받을 수 있을까요?
SELECT 직원.직원ID, 직원.이름, 부서.부서명
FROM 직원
FULL OUTER JOIN 부서 ON 직원.부서ID = 부서.부서ID;
- 모든 튜플을 모두 포함해야합니다.
- FROM 바로 뒤의 테이블부터 엔진은 조인을 시작합니다.
- 장보고까지 조인하면서 부서명이 일치하는 것이 없으면 NULL로 채웁니다.
- 부서 테이블을 다시 조인합니다.
조인 결과
직원ID | 이름 | 부서명 |
---|---|---|
1 | 홍길동 | 개발 |
2 | 이순신 | 마케팅 |
3 | 강감찬 | NULL |
4 | 장보고 | NULL |
NULL | NULL | 인사 |
위 결과를 보면 왼쪽, 오른쪽 조인을 순서대로 한 것과 같습니다.
이렇게 논리적 Joins에서 Outer join인 외부 조인을 알아봤습니다.
정리 #
정리하자면 외부 조인의 경우
- 조인의 주체가 되는 테이블을 먼저 조인하고,
- 다른 테이블을 붙인다.
- 값이 조건에 맞지 않는 경우 NULL을 넣는다.