> ## 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 のサブクエリによって 1 つのクエリが別のクエリの答えを使える仕組み、サブクエリを置ける場所、およびサブクエリが多すぎる行を返したときの ERROR 1242 の意味。

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

サブクエリは、別のクエリの中にあるクエリです。まだ知らない答えを使えるように
します。最も長い映画、平均のレーティング、何かに一致する id の集合などです。
サブクエリがなければ、2 つのクエリを実行し、最初の結果を手作業で 2 番目に
貼り付けることになります。

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

## サブクエリの仕組み

```sql theme={null}
SELECT COLUMN_LIST
FROM TABLE_NAME
WHERE COLUMN_NAME = (SELECT AGGREGATE_FUNCTION(COLUMN_NAME) FROM TABLE_NAME);
```

`COLUMN_LIST` を欲しい列に、`TABLE_NAME` をテーブルに、`COLUMN_NAME` を
テストする列に、`AGGREGATE_FUNCTION` を比較対象の値を生成する関数に
置き換えます。

サーバーはサブクエリを実行し、その結果を受け取って、外側のクエリで使います。

ちょうど 1 行 1 列を返す、かっこで囲まれたサブクエリはスカラーサブクエリ
であり、値のように振る舞います。それが以下の形であり、最もよく問題を起こす
形です。

## 例

### 書き下せない値を使う

最も長い映画の長さは分からないので、その場で求めます。

```sql theme={null}
SELECT title, length
FROM film
WHERE length = (SELECT MAX(length) FROM film)
ORDER BY title;
```

```text theme={null}
+--------------------+--------+
| title              | length |
+--------------------+--------+
| CHICAGO NORTH      |    185 |
| CONTROL ANTHEM     |    185 |
| DARN FORRESTER     |    185 |
...
+--------------------+--------+
10 rows in set (0.00 sec)
```

`MAX(length)` 単独では 185 だけが得られ、それ以外は何も得られません。
サブクエリはそれを `WHERE` に戻すので、映画も得られます。

### 選択リスト内のサブクエリ

同じ値を選択リストに置くこともでき、そこではすべての行で繰り返されます。

```sql theme={null}
SELECT title, length, (SELECT AVG(length) FROM film) AS catalog_mean
FROM film
ORDER BY title
LIMIT 3;
```

```text theme={null}
+------------------+--------+--------------+
| title            | length | catalog_mean |
+------------------+--------+--------------+
| ACADEMY DINOSAUR |     86 |     115.2720 |
| ACE GOLDFINGER   |     48 |     115.2720 |
| ADAPTATION HOLES |     50 |     115.2720 |
+------------------+--------+--------------+
3 rows in set (0.00 sec)
```

サブクエリは 1 回実行され、その答えが列に沿って複製されます。これが、比較
対象の行の横に値を表示する方法です。

### リストを返すサブクエリ

[IN](https://villagesql.com/docs/ja/tutorial/in.md) に渡すサブクエリは多くの行を返すことが許されます。
`IN` は値ではなくリストを期待するためです。

```sql theme={null}
SELECT first_name, last_name
FROM actor
WHERE actor_id IN (SELECT actor_id FROM film_actor WHERE film_id = 1)
ORDER BY last_name
LIMIT 5;
```

```text theme={null}
+------------+-----------+
| first_name | last_name |
+------------+-----------+
| JOHNNY     | CAGE      |
| ROCK       | DUKAKIS   |
| CHRISTIAN  | GABLE     |
| PENELOPE   | GUINESS   |
| MARY       | KEITEL    |
+------------+-----------+
5 rows in set (0.00 sec)
```

内側のクエリは映画 1 に出演する全員の id を返し、`IN` は各俳優をそのリスト
全体に対してテストします。

## ERROR 1242 はサブクエリが多すぎる行を返したことを意味する

`=` は 1 つのものを 1 つのものと比較します。1,000 行を返すサブクエリを与えると、
サーバーは先に進めません。

```sql theme={null}
SELECT title FROM film WHERE length = (SELECT length FROM film);
```

```text theme={null}
ERROR 1242 (21000): Subquery returns more than 1 row
```

意図に応じて、3 つの出口があります。

* リストが欲しかったのなら、`=` の代わりに `IN` を使います。
* 集合から 1 つの値が欲しかったのなら、`MAX()` などの集計関数を追加します。
* どの 1 行でもよく、`ORDER BY` でどれかを指定できるなら、`LIMIT 1` を追加します。

`ERROR 1242` は少なくとも、はっきりエラーを出して失敗します。この間違いの、
エラーを出さない版は、行を 1 つも返さないサブクエリです。それは NULL を返し、比較は
NULL になり、外側のクエリは静かに何も返しません。

## まとめ

* 1 つのクエリの答えを別のクエリに渡すにはサブクエリを使います。
* 1 行 1 列のスカラーサブクエリは値のように振る舞うと考えてください。
* `ERROR 1242` は、多くの行を返したサブクエリに対する `=` として読みます。
* サブクエリがリストを返すときは、`=` ではなく `IN` を使います。
* 外側のクエリがエラーなしに何も返さないときは、空のサブクエリを疑います。

## 関連項目

* [相関サブクエリ](https://villagesql.com/docs/ja/tutorial/correlated-subqueries.md) — 外側の行を読むサブクエリ
* [IN](https://villagesql.com/docs/ja/tutorial/in.md) — サブクエリからのリストを受け入れる演算子
* [派生テーブル](https://villagesql.com/docs/ja/tutorial/derived-tables.md) — テーブルとして使うサブクエリ
* [MySQL におけるサブクエリと JOIN の比較](https://villagesql.com/docs/ja/guides/subqueries-vs-joins.md) — どの形を選ぶか、それぞれのコスト


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