> ## 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 の ORDER BY

> ORDER BY で MySQL の結果をソートする方法: 昇順と降順、複数列の同時指定、エイリアスによるソート、そして 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 →

テーブルには順序がありません。行はサーバーにとって都合のよい順序で返り、
それは実行のたびに変わりえます。結果の順序を決めるものは `ORDER BY` だけです。

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

## ORDER BY の仕組み

```sql theme={null}
SELECT COLUMN_LIST
FROM TABLE_NAME
ORDER BY SORT_COLUMN DIRECTION;
```

`SORT_COLUMN` をソートの基準にする列に置き換えます。`DIRECTION` は、小さい
ものから並べる `ASC` か、大きいものから並べる `DESC` のどちらかです。省略
可能で、省略すると `ASC` になります。

## 例

### 1 つの列でソートする

```sql theme={null}
SELECT title FROM film ORDER BY title;
```

```text theme={null}
+-----------------------------+
| title                       |
+-----------------------------+
| ACADEMY DINOSAUR            |
| ACE GOLDFINGER              |
| ADAPTATION HOLES            |
| AFFAIR PREJUDICE            |
| AFRICAN EGG                 |
...
+-----------------------------+
1000 rows in set (0.01 sec)
```

### 逆順にソートする

```sql theme={null}
SELECT title, rental_rate FROM film ORDER BY rental_rate DESC;
```

```text theme={null}
+-----------------------------+-------------+
| title                       | rental_rate |
+-----------------------------+-------------+
| ACE GOLDFINGER              |        4.99 |
| AIRPLANE SIERRA             |        4.99 |
| AIRPORT POLLOCK             |        4.99 |
| ALADDIN CALENDAR            |        4.99 |
| ALI FOREVER                 |        4.99 |
...
+-----------------------------+-------------+
1000 rows in set (0.00 sec)
```

Sakila はすべての映画に 3 つの料金のいずれか 1 つを付けており、336 本の映画が
最高料金の 4.99 を共有しています。この 336 本の同順位の行の間の順序は
このクエリでは決まらないので、ここに示した順序と異なることがあります。

### 2 つ目の列で同順位を解消する

ソート列を優先順にカンマで区切って並べます。各列はそれぞれの方向を
持ちます。

```sql theme={null}
SELECT title, rental_rate, length
FROM film
ORDER BY rental_rate DESC, length;
```

```text theme={null}
+-----------------------------+-------------+--------+
| title                       | rental_rate | length |
+-----------------------------+-------------+--------+
| IRON MOON                   |        4.99 |     46 |
| HANOVER GALAXY              |        4.99 |     47 |
| ACE GOLDFINGER              |        4.99 |     48 |
| MIDSUMMER GROUNDHOG         |        4.99 |     48 |
| PELICAN COMFORTS            |        4.99 |     48 |
...
+-----------------------------+-------------+--------+
1000 rows in set (0.00 sec)
```

`rental_rate` が依然として先頭で、降順です。各料金の中では最も短い映画が
先に来ます。長さが等しい映画はまだ同順位なので、完全に決まった順序には、
すべての行を一意にするだけの列が必要です。

### エイリアスでソートする

`ORDER BY` は同じクエリの列のエイリアスを指定できます。

```sql theme={null}
SELECT title AS film_title FROM film ORDER BY film_title;
```

```text theme={null}
+-----------------------------+
| film_title                  |
+-----------------------------+
| ACADEMY DINOSAUR            |
| ACE GOLDFINGER              |
| ADAPTATION HOLES            |
...
+-----------------------------+
1000 rows in set (0.00 sec)
```

## エイリアスはシングルクォートではなくバッククォートで囲む

空白を含むエイリアスは引用符で囲む必要があり、ここで 2 つの引用スタイルの
一致が崩れます。シングルクォートは名前ではなく文字列を作り、固定の文字列で
ソートしても何もソートされません。

```sql theme={null}
SELECT title, rental_rate AS 'Rate' FROM film ORDER BY 'Rate';
```

```text theme={null}
+-----------------------------+------+
| title                       | Rate |
+-----------------------------+------+
| ACADEMY DINOSAUR            | 0.99 |
| ACE GOLDFINGER              | 4.99 |
| ADAPTATION HOLES            | 2.99 |
| AFFAIR PREJUDICE            | 2.99 |
| AFRICAN EGG                 | 2.99 |
...
+-----------------------------+------+
1000 rows in set (0.00 sec)
```

料金は 0.99、4.99、2.99 と並んでおり、何もソートされていません。サーバーは
`'Rate'` を 4 文字の単語として読み、すべての行を同じ値でソートしました。
エラーなし、警告なし、ソートなしです。

バッククォートはエイリアスを指し、ソートが行われます。

```sql theme={null}
SELECT title, rental_rate AS `Rate` FROM film ORDER BY `Rate`;
```

```text theme={null}
+-----------------------------+------+
| title                       | Rate |
+-----------------------------+------+
| ACADEMY DINOSAUR            | 0.99 |
| ALAMO VIDEOTAPE             | 0.99 |
| ALASKA PHANTOM              | 0.99 |
| ALICE FANTASIA              | 0.99 |
| ALONE TRIP                  | 0.99 |
...
+-----------------------------+------+
1000 rows in set (0.00 sec)
```

表示されている行はすべて 0.99 なので、それらの間の順序もここでは決まって
いません。

## NULL はどこに並ぶか

列は `NULL` を保持でき、これは値がまったくないことを記録します。ゼロでも
空文字列でもありません。MySQL は `NULL` をすべての実際の値より小さいものとしてソート
するので、昇順では NULL が先頭に来ます。`address` の 603 行のうち、4 行には
`address2` がありません。

```sql theme={null}
SELECT address_id, address2 FROM address ORDER BY address2;
```

```text theme={null}
+------------+----------+
| address_id | address2 |
+------------+----------+
|          1 | NULL     |
|          2 | NULL     |
|          3 | NULL     |
|          4 | NULL     |
|        303 |          |
|        605 |          |
...
+------------+----------+
603 rows in set (0.00 sec)
```

4 つの NULL 行が先に来ます。その後の行は空文字列を保持しており、これは実際の
値なので、`NULL` より大きく、どのテキストよりも小さいものとしてソートされます。この 4 つの
NULL 行は互いに同順位なので、それらの間の順序はこのクエリでは決まりません。

`DESC` はそれを逆にし、NULL は末尾に行きます。これは同じ結果を逆順に
ソートしたものの末尾です。

```sql theme={null}
SELECT address_id, address2 FROM address ORDER BY address2 DESC;
```

```text theme={null}
+------------+----------+
| address_id | address2 |
+------------+----------+
...
|        532 |          |
|          1 | NULL     |
|          2 | NULL     |
|          3 | NULL     |
|          4 | NULL     |
+------------+----------+
603 rows in set (0.00 sec)
```

## まとめ

* 結果の順序を決めるには `ORDER BY` を使います。他に決めるものはありません。
* 大きいものから並べるには `DESC` と書きます。`ASC` がデフォルトです。
* 同順位を解消するには、複数のソート列を優先順に並べます。
* エイリアスでソートするときはバッククォートで囲みます。シングルクォートは文字列を作るからです。
* 昇順では `NULL` が先頭に、降順では末尾に来ます。

## 関連項目

* [SELECT](https://villagesql.com/docs/ja/tutorial/select.md) — ソートされる文
* [列のエイリアス](https://villagesql.com/docs/ja/tutorial/column-aliases.md) — ソートの基準にする列に名前を付ける
* [LIMIT](https://villagesql.com/docs/ja/tutorial/limit.md) — ソートした結果の最初の数行を取る
* [MySQL のページネーション](https://villagesql.com/docs/ja/guides/pagination.md) — 大きなテーブルでソートにかかるコスト


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