> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL 조인의 동작 방식

> MySQL에서 데이터가 왜 여러 테이블로 나뉘는지, 조인이 그것을 어떻게 다시 합치는지, 그리고 내부 조인과 외부 조인과 교차 조인은 무엇이 다른지 설명합니다.

> [card] [VillageSQL is a drop-in replacement for MySQL with extensions.](https://villagesql.com/docs/en/8.4/stable/install-server.md)
>
> All examples on this page work on VillageSQL. Install Now →

지금까지의 모든 쿼리는 테이블 1개를 읽었습니다. 실제 데이터베이스는 정보를 여러 테이블에 퍼뜨려 두고, 조인은 그 테이블들을 가로질러 읽는 방법입니다. 이 수업은 조인이 무엇을 하는지, 그리고 여러 종류의 조인이 각각 무엇을 위한 것인지 설명합니다. 그 뒤의 수업들이 각 종류를 차례로 다룹니다.

시작하기 전에 `mysql -u root -p sakila`로 클라이언트를 여세요.

## 데이터가 나뉘어 있는 이유

Sakila는 각 영화의 언어를 숫자로 기록합니다.

```sql theme={null}
SELECT film_id, title, language_id FROM film ORDER BY film_id LIMIT 3;
```

```text theme={null}
+---------+------------------+-------------+
| film_id | title            | language_id |
+---------+------------------+-------------+
|       1 | ACADEMY DINOSAUR |           1 |
|       2 | ACE GOLDFINGER   |           1 |
|       3 | ADAPTATION HOLES |           1 |
+---------+------------------+-------------+
3 rows in set (0.00 sec)
```

그 숫자에 해당하는 이름은 별도의 테이블에 있습니다.

```sql theme={null}
SELECT language_id, name FROM language ORDER BY language_id;
```

```text theme={null}
+-------------+----------+
| language_id | name     |
+-------------+----------+
|           1 | English  |
|           2 | Italian  |
|           3 | Japanese |
|           4 | Mandarin |
|           5 | French   |
|           6 | German   |
+-------------+----------+
6 rows in set (0.00 sec)
```

`English`라는 단어를 한 번 저장하고 1,000번 가리키는 것이 1,000번 저장하는 것보다 자리를 덜 차지하고, 철자를 고치는 일은 1,000개가 아니라 1개의 행을 바꾸는 일이 됩니다. 그 대가로, 제목과 언어 이름을 원하는 쿼리는 두 테이블을 모두 읽어야 합니다.

## 조인의 동작 방식

```sql theme={null}
SELECT COLUMN_LIST
FROM LEFT_TABLE
JOIN RIGHT_TABLE ON LEFT_TABLE.COLUMN_NAME = RIGHT_TABLE.COLUMN_NAME;
```

`COLUMN_LIST`를 원하는 열로, `LEFT_TABLE`을 시작하는 테이블로, `RIGHT_TABLE`을 추가 열을 가져올 테이블로, 각 `COLUMN_NAME`을 그쪽에서 두 테이블을 연결하는 열로 바꾸세요.

서버는 왼쪽 테이블의 각 행을 가져와서, `ON` 조건이 참인 오른쪽 테이블의 행을 찾고, 일치마다 결합된 행 1개를 반환합니다.

## 예제

### 숫자 대신 이름 읽기

```sql theme={null}
SELECT f.title, l.name
FROM film AS f
JOIN language AS l ON f.language_id = l.language_id
ORDER BY f.title
LIMIT 3;
```

```text theme={null}
+------------------+---------+
| title            | name    |
+------------------+---------+
| ACADEMY DINOSAUR | English |
| ACE GOLDFINGER   | English |
| ADAPTATION HOLES | English |
+------------------+---------+
3 rows in set (0.00 sec)
```

`AS f`와 `AS l`은 테이블 별칭인데, [다음 수업](https://villagesql.com/docs/ko/tutorial/table-aliases.md)이 다룹니다.

## 조인의 종류는 각각 무엇을 위한 것인가

종류들은 1가지에서 다릅니다: 일치를 찾지 못한 행에 무슨 일이 일어나는가입니다.

| 조인 | 남기는 것 |
| - | - |
| `INNER JOIN` | 양쪽에서 일치를 찾은 행만 |
| `LEFT JOIN` | 왼쪽 테이블의 모든 행, 일치 여부와 상관없이 |
| `RIGHT JOIN` | 오른쪽 테이블의 모든 행, 일치 여부와 상관없이 |
| `CROSS JOIN` | 왼쪽의 모든 행을 오른쪽의 모든 행과 짝지은 것 |

외부 조인이 남긴 일치하지 않은 행도 값이 없는 열을 채워야 하고, NULL로 채웁니다. 그래서 `LEFT JOIN` 옆에 [IS NULL](https://villagesql.com/docs/ko/tutorial/is-null.md)이 그렇게 자주 나타납니다: 아무것과도 일치하지 않은 행을 요청하는 방법이기 때문입니다.

`CROSS JOIN`은 아무것도 일치시키지 않으므로 특이한 쪽입니다. 모든 조합을 원할 때 일부러 요청하는 조인이고, `ON` 절을 빠뜨렸을 때 실수로 얻는 조인입니다.

## 키워드보다 조건이 중요합니다

MySQL에서 `JOIN`, `INNER JOIN`, `CROSS JOIN`은 1가지이고, 문법은 그 어느 것에나 `ON` 절을 붙이거나 붙이지 않는 것을 허용합니다. 그러므로 입력한 키워드가 결과를 결정하지 않습니다. `ON` 조건의 존재가 결정합니다: 있으면 일치를 얻고, 없으면 3개의 단어 중 무엇을 썼든 모든 조합을 얻습니다.

서버가 둘을 대신 구분해 주지 않으므로, 일치를 뜻할 때는 `INNER JOIN ... ON`을, 모든 조합을 뜻할 때는 `ON`이 없는 `CROSS JOIN`을 쓰세요. 그러면 키워드는 서버에 대한 지시가 아니라 다음 독자를 위한 메모가 됩니다.

## 요약

* 정보는 테이블마다 나뉘어 있고, 1개의 테이블이 id로 다른 테이블을 가리킵니다.
* 그 테이블들을 쿼리 1개로 가로질러 읽으려면 조인을 사용하세요.
* `ON` 조건은 어느 행끼리 짝인지 정하는 규칙으로 읽으세요.
* 아무것과도 일치하지 않는 행에 무슨 일이 일어나야 하는지에 따라 조인의 종류를 고르세요.
* 외부 조인이 일치 없이 남긴 행의 열에는 NULL이 들어갑니다.

## 함께 보기

* [테이블 별칭](https://villagesql.com/docs/ko/tutorial/table-aliases.md)과 [INNER JOIN](https://villagesql.com/docs/ko/tutorial/inner-join.md) — 짧은 이름, 그리고 일치만 남기는 조인
* [LEFT JOIN](https://villagesql.com/docs/ko/tutorial/left-join.md)과 [RIGHT JOIN](https://villagesql.com/docs/ko/tutorial/right-join.md) — 일치하지 않은 행을 남기는 조인
* [CROSS JOIN](https://villagesql.com/docs/ko/tutorial/cross-join.md)과 [셀프 조인](https://villagesql.com/docs/ko/tutorial/self-join.md) — 모든 조합, 그리고 자기 자신과 조인한 테이블
* [MySQL JOIN 성능과 흔한 실수](https://villagesql.com/docs/ko/guides/joins.md) — 테이블이 커지면 잘못되는 것들


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.