# 조인2 - 외부 조인과 기타 조인

## 외부 조인1&#x20;

내부 조인은 양쪽 테이블에 모두 존재하는 교집합을 찾는 조인 방법이다. \
하지만, 실무에서는 종종 짝이 없는, 소외된 데이터를 찾아야 할 때가 있다.&#x20;

#### 외부 조인의 필요성&#x20;

내부 조인으로는 주문 기록이 없는 고객을 찾을 수 없다. 이런 경우 외부 조인이 필요하다. \
외부 조인을 사용하면 한쪽 테이블에만 존재하는 데이터도 결과에 포함시킬 수 있다.&#x20;

이처럼 한쪽에는 데이터가 있지만, 다른 한쪽에는 없는 데이터까지 모두 포함해서 보고 싶을 때 사용하는 기술이 바로 외부 조인이다.&#x20;

### 외부 조인의 필요성 및 개념&#x20;

#### 외부 조인의 필요성&#x20;

외부 조인은 두 테이블을 조인할 때, 특정 테이블의 데이터는 `ON` 조건에 맞지 않더라도 모두 결과에 포함시키는 방법이다.&#x20;

<figure><img src="https://2093748731-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQMqxl0iBPcO3zyZX5B19%2Fuploads%2FAdCgkcF7NV0kRZ0YgLNl%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-08-14%2010.01.17.png?alt=media&#x26;token=2dc39df7-6145-4180-9d36-03f19606427f" alt=""><figcaption></figcaption></figure>

이때 기준이 되는 테이블이 어느쪽이냐에 따라서 `LEFT OUTER JOIN`, `RIGHT OUTER JOIN` 으로 나뉜다. \
**그리고 교집합 영역은 물론이고, 기준이 되는 테이블의 데이터는 결과에 모두 포함한다.**&#x20;

### 실습1 : LEFT JOIN 으로 '한 번도 주문하지 않은 고객' 찾기&#x20;

첫 번째 질문, "한 번도 주문하지 않은 고객은 누구인가?" 에 답을 찾아보자. 이 질문의 기준은 '고객'이다. 따라서 `users` 테이블이 `LEFT JOIN` 의 왼쪽에 위치한다.&#x20;

1. `users` 를 기준으로 `orders` 테이블 `LEFT JOIN` 하기

```sql
SELECT
    u.user_id,
    u.name,
    o.user_id,
    o.order_id
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
ORDER BY u.user_id;
```

\[조인 결과 - LEFT JOIN]&#x20;

<figure><img src="https://2093748731-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQMqxl0iBPcO3zyZX5B19%2Fuploads%2FOlWhfN6iiMC1b0qfuo6N%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-08-14%2010.05.01.png?alt=media&#x26;token=39171d50-29a5-4dd2-9c74-209014d29b55" alt="" width="563"><figcaption></figcaption></figure>

2. NULL 인 데이터만 필터링하기&#x20;

```sql
SELECT
    u.user_id,
    u.name,
    u.email
FROM users AS u
LEFT JOIN orders AS o ON u.user_id = o.user_id
WHERE o.order_id IS NULL;
```

\[실행 결과]&#x20;

<figure><img src="https://2093748731-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQMqxl0iBPcO3zyZX5B19%2Fuploads%2FU9PzykvVaP3LgKNjmlNX%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-08-14%2010.06.39.png?alt=media&#x26;token=1e14a8d8-5a49-4f02-9dc0-2fc9d7a7d5a3" alt=""><figcaption></figcaption></figure>

`RIGHT JOIN` 도 기준이 되는 테이블을 어디로 할 것인지만 바꾸어서 생각하보면 동작 방식은 동일하다!&#x20;

### LEFT JOIN, RIGHT JOIN 의 선택&#x20;

`LEFT JOIN` 과 `RIGHT JOIN` 은 서로 위치를 바꾸어 사용할 수 있다.&#x20;

#### 실무에서는 `LEFT JOIN` 이 `RIGHT JOIN` 을 훨씬 많이 사용한다.&#x20;

보통 분석의 기준이 되는 테이블을 `FROM` 절에 먼저 쓰고, 필요한 정보를 담은 다른 테이블들을 `LEFT JOIN` 으로 하나씩 \
붙여나가는 방식으로 쿼리를 작성하는 것이 더 직관적이기 때문이다.&#x20;

## 조인의 특징&#x20;

두 테이블을 조인할 때 어떤 경우 행이 더 늘어나고 어떤 경우에는 행이 늘어나지 않고 그대로인 경우가 있다.&#x20;

### 조인에서 데이터가 늘어나는 경우&#x20;

조인은 다음과 같은 특징이 있다.

**기준으로 삼는 테이블의 한 행(Row)이 다른 쪽 테이블의 여러 행과 연결될 수 있다면**, 결과의 전체 행 수는 늘어난다.\
반대로 **한 행이 다른 쪽 테이블의 단 하나의 행과 연결되거나, 아무 행과도 연결되지 않는다면** 행의 수는 늘어나지 않는다.

그렇다면 대체 언제 행이 늘어나고, 언제 그대로일까? \
이 원리를 이해하려면 테이블 간의 관계, 특히 기본 키와 외래 키의 관계를 알아야 한다.&#x20;

<figure><img src="https://2093748731-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FQMqxl0iBPcO3zyZX5B19%2Fuploads%2FaD8WRdJLEpRzZwx4Tsp5%2F%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202025-08-14%2010.14.31.png?alt=media&#x26;token=b8a9dbfa-8b04-427b-bc32-484397043ad4" alt=""><figcaption></figcaption></figure>

* 기본키 : 테이블에서 각 행을 고유하게 식별하는 값이다. **기본키는 절대 중복될 수 없다.**
* 외래키 : 다른 테이블의 기본키를 참조하는 값이다. 외래키는 참조하는 테이블에서 여러 번 중복되어 나타날 수 있다. \
  예를 들어, 한 명의 고객은 여러번의 주문을 할 수 있기 때문이다.&#x20;

이 관계를 부모-자식 관계에 비유하면 이해가 쉽다.&#x20;

* 부모 테이블 : 기본 키를 가지고 있는 테이블 (`users`, `products`)&#x20;
* 자식 테이블 : 외래 키를 통해 부모 테이블을 참조하는 테이블 (`orders`)

이 개념을 바탕으로 조인 시 데이터 행 수가 어떻게 변하는지 정리하면 다음과 같다.&#x20;

1. 자식 -> 부모 조인(FK -> PK 참조) : 행 개수가 늘어나지 않는다.&#x20;
   1. `orders` 테이블을 기준으로 `users` 테이블을 조인하는 경우이다.&#x20;
   2. 자식 테이블의 각 주문 정보는 반드시 단 한명의 부모하고만 연결된다. 주문 하나가 여러 고객의 것일 수는 없기 때문이다. 따라서 기준 테이블인 orders 의 행 개수가 그대로 유지된다.&#x20;
   3. PK 는 유일한 하나의 값만 저장된다. 따라서 PK 방향으로 참조하는 경우 행 개수가 늘어나지 않는다.&#x20;
2. 부모 -> 자식 조인(PK -> FK 참조) : 행 개수가 늘어날 수 있다.&#x20;
   1. `users` 테이블을 기준으로 `orders` 테이블을 조인하는 경우다.&#x20;
   2. 부모 테이블의 한 고객이 여러 명의 자식을 가질 수 있다. 이 경우, 한 고객의 정보를 여러 주문 정보에 각각 매칭시켜야 하므로, 고객 정보 행이 전체 건수만큼 복제되어 전체 행의 수가 늘어난다.&#x20;
   3. FK 는 같은 값을 여러개 저장할 수 있다. 따라서 FK 방향으로 참조하는 경우 행 개수가 늘어날 수 있다.&#x20;

#### 실무에서 이게 왜 중요할까?&#x20;

이 원리를 모르면 데이터를 잘못 분석하게 될 가능성이 크다.&#x20;

예를 들어, 모든 고객과 그들의 주문정보를 보기 위해 `FROM users JOIN orders` 를 수행했다고 하자. 이 결과에서 고객 수를 세기 위해 `COUNT(u.user_id)` 를 실행하면 어떻게 될까? 전체 고객 수인 6이 나올까? 아니다. 주문을 여러 번 한 고객이 중복 계산되므로, 전체 주문 수인 7이 나온다.&#x20;

이처럼 조인으로 인해 데이터가 어떻게 변하는지 정확히 이해해야만 집계 함수를 올바르게 사용할 수 있다. 쿼리를 작성하기 전 어떤 테이블을 기준으로 삼을지, 그리고 조인으로 인해 행 수가 늘어나는 상황인지 아닌지 생각하는 습관을 들이는 것이 중요하다.&#x20;
