> ## 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 の IN

> MySQL の IN 演算子が 1 つの列を値のリストと比較する仕組み、NOT IN との違い、そしてリストのどこかに NULL があると NOT IN が何も返さなくなる理由。

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

`IN` は 1 つの列を複数の値と一度に比較します。`OR` をつなげたものと同じ
ことを 1 つの句で表し、フィルタの値が 2 つを超えたときに多くの人が使う句です。

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

## IN の仕組み

```sql theme={null}
SELECT COLUMN_LIST
FROM TABLE_NAME
WHERE COLUMN_NAME IN (FIRST_VALUE, SECOND_VALUE);
```

`COLUMN_NAME` をテストする列に、`FIRST_VALUE` と `SECOND_VALUE` を受け入れる
値に置き換えます。

条件は、列が括弧内のいずれかの値と等しいときに真になります。値はカンマで
区切り、必要なだけ並べられます。

`x IN (a, b)` は `x = a OR x = b` と同じ意味です。読みやすいほうを書いて
ください。値が 2 つを超えると `IN` のほうが読みやすくなります。

## 例

### 複数の値のいずれかに一致する

```sql theme={null}
SELECT title, rating
FROM film
WHERE rating IN ('G', 'PG')
ORDER BY title
LIMIT 5;
```

```text theme={null}
+------------------+--------+
| title            | rating |
+------------------+--------+
| ACADEMY DINOSAUR | PG     |
| ACE GOLDFINGER   | G      |
| AFFAIR PREJUDICE | G      |
| AFRICAN EGG      | G      |
| AGENT TRUMAN     | PG     |
+------------------+--------+
5 rows in set (0.00 sec)
```

### どれにも一致しない

```sql theme={null}
SELECT title, rating
FROM film
WHERE rating NOT IN ('G', 'PG')
ORDER BY title
LIMIT 5;
```

```text theme={null}
+------------------+--------+
| title            | rating |
+------------------+--------+
| ADAPTATION HOLES | NC-17  |
| AIRPLANE SIERRA  | PG-13  |
| AIRPORT POLLOCK  | R      |
| ALABAMA DEVIL    | PG-13  |
| ALADDIN CALENDAR | NC-17  |
+------------------+--------+
5 rows in set (0.00 sec)
```

### 数値のリスト

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

```text theme={null}
+------------+--------------+
| first_name | last_name    |
+------------+--------------+
| PENELOPE   | GUINESS      |
| JOHNNY     | LOLLOBRIGIDA |
| CHRISTIAN  | GABLE        |
+------------+--------------+
3 rows in set (0.00 sec)
```

数値には引用符を付けません。行が `actor_id` 順に返るのは `ORDER BY` で
そう指定したからであり、リストがその順に並んでいるからではありません。

### サーバーが自分で求めるリスト

括弧の中にはリストの代わりにクエリを書けます。`film_actor` は各映画と
その出演俳優を組み合わせるテーブルなので、このクエリは映画の id を 1 つも
知らなくても、俳優 1 が出演する映画を求めます。

```sql theme={null}
SELECT title
FROM film
WHERE film_id IN (SELECT film_id FROM film_actor WHERE actor_id = 1)
ORDER BY title
LIMIT 5;
```

```text theme={null}
+-----------------------+
| title                 |
+-----------------------+
| ACADEMY DINOSAUR      |
| ANACONDA CONFESSIONS  |
| ANGELS LIFE           |
| BULWORTH COMMANDMENTS |
| CHEAPER CLYDE         |
+-----------------------+
5 rows in set (0.00 sec)
```

別のクエリの中に書かれたクエリをサブクエリと呼びます。後のセクションで
きちんと扱います。ここで 1 つ見ておく価値があるのは、多くの人が最初に
サブクエリを書く場所が `IN` のリストだからです。

## リスト内の NULL は NOT IN を壊す

`IN` と `NOT IN` はリスト内の NULL を同じようには扱いません。そして
どちらも警告を出しません。

`IN` では、リスト内の NULL は無害です。実際の値に一致する行はそのまま
残ります。

```sql theme={null}
SELECT title, rating
FROM film
WHERE rating IN ('G', NULL)
ORDER BY title
LIMIT 3;
```

```text theme={null}
+------------------+--------+
| title            | rating |
+------------------+--------+
| ACE GOLDFINGER   | G      |
| AFFAIR PREJUDICE | G      |
| AFRICAN EGG      | G      |
+------------------+--------+
3 rows in set (0.00 sec)
```

`NOT IN` では、同じリストがまったく何も返しません。

```sql theme={null}
SELECT title, rating
FROM film
WHERE rating NOT IN ('G', NULL)
ORDER BY title
LIMIT 3;
```

```text theme={null}
Empty set (0.01 sec)
```

すべての映画にはレーティングがあり、そのうち 822 本は `G` ではないので、
空の結果は意外です。理由は、`NOT IN` が「列がリスト内のすべての値と
異なるか」を問うものであり、NULL と異なることは何についても示せないからです。
何かを NULL と比較すると、真でも偽でもなく NULL になるため、条件全体が
決して真にならず、どの行も残りません。

これが最も問題になるのはリストがサブクエリのときです。自分で手書きして
いないサブクエリは、予期しない NULL を返すことがあるからです。可能な
場合は、サブクエリの中に `WHERE COLUMN_NAME IS NOT NULL` を加えてください。
[IS NULL](https://villagesql.com/docs/ja/tutorial/is-null.md) のレッスンでは、NULL がどう比較されるかを
扱います。

## まとめ

* 1 つの列を値のリストと 1 つの句で比較するには `IN` を使います。
* `x IN (a, b)` は `x = a OR x = b` と読みます。
* リスト内の文字列は引用符で囲み、数値はそのまま書きます。
* リスト自体が 1 つの答えであるときは、括弧の中にサブクエリを置きます。
* `NOT IN` のリストに NULL を入れないでください。行がまったく返らなくなります。

## 関連項目

* [AND、OR、NOT](https://villagesql.com/docs/ja/tutorial/and-or-not.md) — IN が置き換える OR の連鎖
* [IS NULL](https://villagesql.com/docs/ja/tutorial/is-null.md) — NULL との比較が真でも偽でもない理由
* [BETWEEN](https://villagesql.com/docs/ja/tutorial/between.md) — リストではなく範囲をテストする
* [サブクエリ](https://villagesql.com/docs/ja/tutorial/subqueries.md) — 例 4 で使ったクエリの形


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