> ## 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/ja/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 つの文の間だけ存続します。保存されず、次のクエリはそれについて何も
知りません。

## 例

### 名前付きのステップ 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` を読み、メインクエリは両方を読みます。派生テーブルとして
書くと、集計クエリは 2 回現れることになります。

## CTE が派生テーブルより優れている点

行はどちらでも同じです。異なるのは 2 点です。

* CTE は名前を持つため、3 段階のクエリが上から下へ読めます。`counts` と
  `busiest` は、次の読者に各部品が何のためのものかを伝えます。
* CTE は同じ文の中で名前で複数回参照できます。派生テーブルはもう一度書き出さなければ
  なりません。

オプティマイザが 2 つの形を異なる扱いにするかどうかは別の問題であり、
[MySQL の CTE が派生テーブルより優れる場合](https://villagesql.com/docs/ja/guides/ctes-in-mysql.md)がそれを
計測しています。

## まとめ

* それを読むクエリの前にクエリに名前を付けるには `WITH name AS (...)` を使います。
* 複数の CTE はカンマで区切り、後の CTE に前の CTE を読ませます。
* CTE は 1 つの文の間だけ存続すると考えてください。
* クエリが複数の段階を持つ、または同じサブクエリを繰り返すときは CTE を使います。

## 関連項目

* [派生テーブル](https://villagesql.com/docs/ja/tutorial/derived-tables.md) — 同じ考えをインラインで書いたもの
* [再帰 CTE](https://villagesql.com/docs/ja/tutorial/recursive-cte.md) — 自分自身を読む CTE
* [GROUP BY](https://villagesql.com/docs/ja/tutorial/group-by.md) — 内側のステップが通常行うこと
* [MySQL の CTE が派生テーブルより優れる場合](https://villagesql.com/docs/ja/guides/ctes-in-mysql.md) — オプティマイザがそれらをどう扱うか


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