> ## 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 WITH 절이 쿼리에 이름을 붙여 주 쿼리가 읽을 수 있게 하는 방법, 여러 개를 한 번에 정의하는 방법, 그리고 CTE가 파생 테이블보다 읽기 좋은 때입니다.

> [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 →

공통 테이블 표현식은 쿼리에 이름을 주는데, 맨 위에, 그것을 사용하는 쿼리보다 앞에 둡니다. 결과는 [파생 테이블](https://villagesql.com/docs/ko/tutorial/derived-tables.md)과 같고, 생각하는 순서대로 읽힙니다: 조각을 정의한 다음, 그것을 사용합니다.

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

## CTE의 동작 방식

```sql theme={null}
WITH CTE_NAME AS (
  SELECT COLUMN_LIST FROM TABLE_NAME
)
SELECT COLUMN_LIST FROM CTE_NAME;
```

`CTE_NAME`을 중간 결과의 이름으로, `COLUMN_LIST`를 원하는 열로, `TABLE_NAME`을 안쪽 쿼리가 읽는 테이블로 바꾸세요. 그러면 주 쿼리는 `CTE_NAME`을 테이블인 것처럼 읽습니다.

CTE는 1개의 문장 동안 유지됩니다. 저장되지 않고, 다음 쿼리는 그것에 대해 아무것도 모릅니다.

## 예제

### 이름 붙인 단계 하나

```sql theme={null}
WITH counts AS (
  SELECT rating, COUNT(*) AS films FROM film GROUP BY rating
)
SELECT rating, films FROM counts WHERE films > 200 ORDER BY rating;
```

```text theme={null}
+--------+-------+
| rating | films |
+--------+-------+
| PG-13  |   223 |
| NC-17  |   210 |
+--------+-------+
2 rows in set (0.00 sec)
```

파생 테이블 레슨이 반환하는 것과 같은 행이며, 세는 부분을 `FROM`에서 꺼내어 이름을 붙였습니다.

### 각각 앞 단계 위에 쌓은 여러 단계

CTE는 쉼표로 구분하고, 뒤의 CTE는 앞의 CTE를 읽을 수 있습니다. 이것은 파생 테이블이 자신을 반복하지 않고는 할 수 없는 일입니다.

```sql theme={null}
WITH counts AS (
  SELECT rating, COUNT(*) AS films FROM film GROUP BY rating
),
busiest AS (
  SELECT MAX(films) AS most FROM counts
)
SELECT c.rating, c.films
FROM counts AS c
INNER JOIN busiest AS b ON c.films = b.most;
```

```text theme={null}
+--------+-------+
| rating | films |
+--------+-------+
| PG-13  |   223 |
+--------+-------+
1 row in set (0.00 sec)
```

`busiest`가 `counts`를 읽고, 주 쿼리가 둘 다를 읽습니다. 파생 테이블로 쓰면 세는 쿼리가 두 번 나타날 것입니다.

## CTE가 주고 파생 테이블은 주지 않는 것

행은 어느 쪽이든 같습니다. 2가지가 다릅니다:

* CTE는 이름을 가지므로, 3단계 쿼리가 위에서 아래로 읽힙니다. `counts`와 `busiest`는 다음 독자에게 각 조각이 무엇을 위한 것인지 말해 줍니다.
* CTE는 같은 문장 안에서 두 번 이상 이름으로 부를 수 있습니다. 파생 테이블은 다시 써 내야 합니다.

옵티마이저가 2가지 형태를 다르게 다루는지는 별개의 문제이고, [MySQL CTE가 파생 테이블을 이기는 때](https://villagesql.com/docs/ko/guides/ctes-in-mysql.md)가 그것을 측정합니다.

## 요약

* 쿼리를 읽는 쿼리보다 앞에서 그 쿼리에 이름을 붙이려면 `WITH name AS (...)`를 사용하세요.
* 여러 CTE는 쉼표로 구분하고, 뒤의 CTE가 앞의 CTE를 읽게 하세요.
* CTE는 1개의 문장 동안만 유지된다고 예상하세요.
* 쿼리에 여러 단계가 있거나 서브쿼리를 반복할 때는 CTE를 쓰세요.

## 함께 보기

* [파생 테이블](https://villagesql.com/docs/ko/tutorial/derived-tables.md) — 같은 아이디어를 인라인으로
* [재귀 CTE](https://villagesql.com/docs/ko/tutorial/recursive-cte.md) — 자기 자신을 읽는 CTE
* [GROUP BY](https://villagesql.com/docs/ko/tutorial/group-by.md) — 안쪽 단계가 보통 하는 일
* [MySQL CTE가 파생 테이블을 이기는 때](https://villagesql.com/docs/ko/guides/ctes-in-mysql.md) — 옵티마이저가 그것들을 다루는 방법


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