> ## 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 の派生テーブル

> FROM 句のサブクエリがクエリできるテーブルになる仕組み、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 →

`WHERE` のサブクエリは値を供給します。`FROM` のサブクエリはテーブル全体を供給し、
外側のクエリはそれを実在するテーブルであるかのように読みます。それが派生テーブル
であり、クエリの結果をクエリする方法です。

始める前に `mysql -u root -p sakila` でクライアントを開いてください。

## 派生テーブルの仕組み

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

`COLUMN_LIST` を必要な列に、`TABLE_NAME` を内側のクエリが読むテーブルに、
`ALIAS_NAME` を結果の名前に置き換えます。内側のクエリの列名は、エイリアスを含めて、
派生テーブルの列になります。

サーバーはまず内側の結果を作り、それから外側のクエリをその上で実行します。

## 可能になること

`GROUP BY` は詳細行をグループごとの 1 行に置き換えるため、グループ化したクエリは
行そのものを見せてくれません。派生テーブルは両方を保ちます。内側のクエリで
グループ化し、その結果を詳細に結合し直します。

これは、自分のレーティングの平均より長い映画を一覧にし、それぞれの横にその平均を
示します。

```sql theme={null}
SELECT f.title, f.length, r.mean_for_rating
FROM film AS f
INNER JOIN (
  SELECT rating, AVG(length) AS mean_for_rating
  FROM film
  GROUP BY rating
) AS r ON r.rating = f.rating
WHERE f.length > r.mean_for_rating
ORDER BY f.rating, f.title
LIMIT 5;
```

```text theme={null}
+------------------+--------+-----------------+
| title            | length | mean_for_rating |
+------------------+--------+-----------------+
| AFFAIR PREJUDICE |    117 |        111.0506 |
| AFRICAN EGG      |    130 |        111.0506 |
| ALAMO VIDEOTAPE  |    126 |        111.0506 |
| ATLANTIS CAUSE   |    170 |        111.0506 |
| BAKED CLEOPATRA  |    182 |        111.0506 |
+------------------+--------+-----------------+
5 rows in set (0.00 sec)
```

`WHERE` も [HAVING](https://villagesql.com/docs/ja/tutorial/having.md) も、単独ではこれを書けません。`HAVING`
はグループをフィルタするのでタイトルを捨ててしまい、`WHERE` はどの平均も存在
しないうちに実行されます。5 つの平均は内側のクエリで 1 回計算され、結合が正しい
ものを各映画に付けます。

[相関サブクエリ](https://villagesql.com/docs/ja/tutorial/correlated-subqueries.md)のレッスンは、同じ質問に
1 行ずつ答えます。この形は代わりに平均を 1 回だけ計算します。

## エイリアスは省略できない

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

```text theme={null}
ERROR 1248 (42000): Every derived table must have its own alias
```

`ERROR 1248` は常にこの意味で、修正も常に同じです。閉じ括弧の後に `AS SOME_NAME`
を置きます。名前は何でも構いませんが、行の内容を表すものにする価値があります。
読者は、その行を生成したクエリを読む前にその名前に出会うからです。

## 派生テーブルか CTE か

[共通テーブル式](https://villagesql.com/docs/ja/tutorial/cte.md)は、サブクエリを先頭に取り出して名前を付け、
同じ仕事をします。2 つの形は同じ行を生成し、次のレッスンでその違いを扱います。
[MySQL の CTE が派生テーブルより優れる場合](https://villagesql.com/docs/ja/guides/ctes-in-mysql.md)は、
オプティマイザがどちらを異なる扱いにするかを計測しています。

## まとめ

* クエリの結果をクエリするには派生テーブルを使います。
* エイリアスを付けます。付けないと `ERROR 1248` が返ります。
* 内側のクエリの列エイリアスが派生テーブルの列になると考えてください。
* 計算した列でフィルタや結合をする必要があるときに使います。
* クエリが複数の段階を持つ、または同じサブクエリを繰り返すようになったら CTE を使います。

## 関連項目

* [共通テーブル式](https://villagesql.com/docs/ja/tutorial/cte.md) — 同じ考えを先頭に書いたもの
* [HAVING](https://villagesql.com/docs/ja/tutorial/having.md) — 派生テーブルなしでグループをフィルタする
* [サブクエリ](https://villagesql.com/docs/ja/tutorial/subqueries.md) — 代わりに値として使うサブクエリ
* [MySQL の CTE が派生テーブルより優れる場合](https://villagesql.com/docs/ja/guides/ctes-in-mysql.md) — オプティマイザが 2 つを異なる扱いにする場合


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