> ## 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 の COUNT DISTINCT

> MySQL で COUNT(DISTINCT column) が行ではなく異なる値を数える仕組み、異なる組み合わせを数える方法、および NULL を完全に飛ばす理由。

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

`COUNT(*)` は行がいくつあるかに答えます。`COUNT(DISTINCT column)` は異なる値が
いくつあるかに答えます。初めて見る列については、たいていこちらのほうが興味深い
質問です。

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

## COUNT DISTINCT の仕組み

```sql theme={null}
SELECT COUNT(DISTINCT COLUMN_NAME)
FROM TABLE_NAME;
```

`COLUMN_NAME` を異なる値を数えたい列に、`TABLE_NAME` をテーブルに置き換えます。
サーバーはすべての行を読み、重複を捨て、残ったものを数えます。

これは [SELECT DISTINCT](https://villagesql.com/docs/ja/tutorial/select-distinct.md) が返すものの件数を、それを
返さずに得るものです。

## 例

### 異なる値はいくつあるか

```sql theme={null}
SELECT COUNT(*) AS rows_total, COUNT(DISTINCT rating) AS ratings FROM film;
```

```text theme={null}
+------------+---------+
| rows_total | ratings |
+------------+---------+
|       1000 |       5 |
+------------+---------+
1 row in set (0.01 sec)
```

1,000 本の映画が 5 つのレーティングに分類されています。

### 異なる組み合わせ

複数の列を指定すると、`GROUP BY` と同じように、1 つの組み合わせが 1 回
数えられます。

```sql theme={null}
SELECT COUNT(DISTINCT rating, rental_rate) AS combinations FROM film;
```

```text theme={null}
+--------------+
| combinations |
+--------------+
|           15 |
+--------------+
1 row in set (0.00 sec)
```

5 つのレーティングかける 3 つの料金で、すべての組み合わせが現れます。指定した
列のいずれかが NULL の行は、まったく数えられません。

## NULL を飛ばすため、答えが間違って見えることがある

`address2` は 4 行で NULL、残りの 599 行で空文字列です。

```sql theme={null}
SELECT COUNT(*) AS rows_total,
       COUNT(DISTINCT address2) AS distinct_values
FROM address;
```

```text theme={null}
+------------+-----------------+
| rows_total | distinct_values |
+------------+-----------------+
|        603 |               1 |
+------------+-----------------+
1 row in set (0.00 sec)
```

答えは 1 です。空文字列は異なる値として 1 つ数えられ、NULL はそれ自体の値として
数えられるのではなく飛ばされます。つまり、一部の行が空のとき、この関数が答える
のは「この列には何種類の異なるものがあるか」ではありません。答えるのは「異なる
値はいくつあるか」で、NULL は値の不在です。

両方の数が必要なときは、2 つ目のクエリで欠けている行を数えます。
`SELECT COUNT(*) FROM address WHERE address2 IS NULL` です。

## まとめ

* 行ではなく異なる値を数えるには `COUNT(DISTINCT column)` を使います。
* 異なる組み合わせを数えるには、複数の列を指定します。
* NULL は値として数えられず、飛ばされると考えてください。
* 両方の数が必要なときは、欠けている行を別に数えます。

## 関連項目

* [集計関数](https://villagesql.com/docs/ja/tutorial/aggregate-functions.md) — 同じ仲間の残り
* [SELECT DISTINCT](https://villagesql.com/docs/ja/tutorial/select-distinct.md) — 数える代わりにそれらの値を返す
* [GROUP BY](https://villagesql.com/docs/ja/tutorial/group-by.md) — カテゴリごとに数える
* [MySQL の GROUP BY のパフォーマンス](https://villagesql.com/docs/ja/guides/group-by-having.md) — 大規模な重複排除のコスト


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