【エンジニア教材】MySQL編(2) ソートについて (ORDER BY,LIMIT)

#　【エンジニア教材】MySQL編(2) ソートについて (ORDER BY,LIMIT)


## まえがき

このドキュメントは社員やインターン生を教育するために作成したものですが、
ぜひ社外の人にも見ていただきたいと思い公開いたしました。

ちょこちょこ更新しますのでリクエストなどございましたらお気軽にお申し付け下さい。
体系的に書き進めていくのでリクエストしていただいたものについてすぐかける保証はございませんのでご理解とご了承のほどよろしくお願いいたします。
もし役に立ったら、いいね！やストックをしてもらえると励みになりますm(_ _)m

ちなみにプロフィールはこちら。
https://www.wantedly.com/users/1955894

## SELECT文でORDER BY,LIMITを理解する。

今回はSELECT文でORDER BY,LIMITを使ってレコードを取得するということをやって見ます。
はじめにデータを用意します。
今回はテスト用のデータをランダムに生成してくれるこちらのサイトを用いてデータをインポートしました。
http://kazina.com/dummy/index.html

同じデータを用いて試して見たいという方は次のSQLを実行してデータを入れて見てください。

```
CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `name_kana` varchar(100) DEFAULT NULL,
  `email` varchar(100) DEFAULT NULL,
  `gender` varchar(10) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `blood_type` varchar(10) DEFAULT NULL,
  `birthday` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `users` (`id`, `name`, `name_kana`, `email`, `gender`, `age`, `blood_type`, `birthday`)
VALUES
	(1,'大村郁恵','おおむらいくえ','oomuraikue@example.com','F',39,'B','1978/1/23'),
	(2,'片岡寿明','かたおかとしあき','kataokatoshiaki@example.com','M',21,'A','1995/4/21'),
	(3,'岡島慎之介','おかじましんのすけ','okajimashinnosuke@example.com','M',20,'O','1997/2/4'),
	(4,'中田英嗣','なかたひでつぐ','nakatahidetsugu@example.com','M',23,'AB','1994/1/3'),
	(5,'藤村涼子','ふじむらりょうこ','fujimuraryouko@example.com','F',33,'O','1984/1/28'),
	(6,'相川一輝','あいかわかずき','aikawakazuki@example.com','M',35,'A','1981/8/18'),
	(7,'野崎由美子','のざきゆみこ','nozakiyumiko@example.com','F',12,'O','2005/1/20'),
	(8,'井口愛子','いぐちあいこ','iguchiaiko@example.com','F',18,'B','1998/8/6'),
	(9,'小森愛','こもりあい','komoriai@example.com','F',30,'O','1986/7/17'),
	(10,'那須由美子','なすゆみこ','nasuyumiko@example.com','F',13,'A','2003/10/5');
```

でははじめていきます。



## ORDER BYを用いて取得結果をソートする。
普段SELECT文を実行するとidの昇順で取得できますが、
そのままだと必ずその順番で取得できるという保証はありません。
一般的にはORDER BYによって順序を明示する必要があります。

ORDER BYを使ったSQLは次のように書きます。

```
SELECT * FROM テーブル名 ORDER BY ソートするカラム ソート順
```

それでは、idではないカラムでORDER BYをやってみることにします。

例：年齢を昇順で全件取得する。

```
mysql> SELECT * FROM users ORDER BY age ASC;
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
|  7 | 野崎由美子      | のざきゆみこ                | nozakiyumiko@example.com      | F      |   12 | O          | 2005/1/20 |
| 10 | 那須由美子      | なすゆみこ                  | nasuyumiko@example.com        | F      |   13 | A          | 2003/10/5 |
|  8 | 井口愛子        | いぐちあいこ                | iguchiaiko@example.com        | F      |   18 | B          | 1998/8/6  |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  4 | 中田英嗣        | なかたひでつぐ              | nakatahidetsugu@example.com   | M      |   23 | AB         | 1994/1/3  |
|  9 | 小森愛          | こもりあい                  | komoriai@example.com          | F      |   30 | O          | 1986/7/17 |
|  5 | 藤村涼子        | ふじむらりょうこ            | fujimuraryouko@example.com    | F      |   33 | O          | 1984/1/28 |
|  6 | 相川一輝        | あいかわかずき              | aikawakazuki@example.com      | M      |   35 | A          | 1981/8/18 |
|  1 | 大村郁恵        | おおむらいくえ              | oomuraikue@example.com        | F      |   39 | B          | 1978/1/23 |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
10 rows in set (0.00 sec)
```

ASCは昇順の意味です。
ソート順には昇順であるASCと、降順であるDESCを指定することができます。
ソート順を指定していないとデフォルトではASCになります。

例：年齢を降順で全件取得する。

```
mysql> SELECT * FROM users ORDER BY age DESC;
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
|  1 | 大村郁恵        | おおむらいくえ              | oomuraikue@example.com        | F      |   39 | B          | 1978/1/23 |
|  6 | 相川一輝        | あいかわかずき              | aikawakazuki@example.com      | M      |   35 | A          | 1981/8/18 |
|  5 | 藤村涼子        | ふじむらりょうこ            | fujimuraryouko@example.com    | F      |   33 | O          | 1984/1/28 |
|  9 | 小森愛          | こもりあい                  | komoriai@example.com          | F      |   30 | O          | 1986/7/17 |
|  4 | 中田英嗣        | なかたひでつぐ              | nakatahidetsugu@example.com   | M      |   23 | AB         | 1994/1/3  |
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
|  8 | 井口愛子        | いぐちあいこ                | iguchiaiko@example.com        | F      |   18 | B          | 1998/8/6  |
| 10 | 那須由美子      | なすゆみこ                  | nasuyumiko@example.com        | F      |   13 | A          | 2003/10/5 |
|  7 | 野崎由美子      | のざきゆみこ                | nozakiyumiko@example.com      | F      |   12 | O          | 2005/1/20 |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
10 rows in set (0.00 sec)
```

複数のカラムでソートすることもできます。
はじめに書いたカラムのほうが優先されます。

```
mysql> SELECT * FROM users ORDER BY gender ASC, blood_type ASC;
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| 10 | 那須由美子      | なすゆみこ                  | nasuyumiko@example.com        | F      |   13 | A          | 2003/10/5 |
|  1 | 大村郁恵        | おおむらいくえ              | oomuraikue@example.com        | F      |   39 | B          | 1978/1/23 |
|  8 | 井口愛子        | いぐちあいこ                | iguchiaiko@example.com        | F      |   18 | B          | 1998/8/6  |
|  5 | 藤村涼子        | ふじむらりょうこ            | fujimuraryouko@example.com    | F      |   33 | O          | 1984/1/28 |
|  7 | 野崎由美子      | のざきゆみこ                | nozakiyumiko@example.com      | F      |   12 | O          | 2005/1/20 |
|  9 | 小森愛          | こもりあい                  | komoriai@example.com          | F      |   30 | O          | 1986/7/17 |
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  6 | 相川一輝        | あいかわかずき              | aikawakazuki@example.com      | M      |   35 | A          | 1981/8/18 |
|  4 | 中田英嗣        | なかたひでつぐ              | nakatahidetsugu@example.com   | M      |   23 | AB         | 1994/1/3  |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
10 rows in set (0.00 sec)
```

genderの方がはじめにソートされ、それぞれのgenderの中でblood_typeがソートされていることがわかります。

```
mysql> SELECT * FROM users ORDER BY blood_type ASC , gender ASC;
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| 10 | 那須由美子      | なすゆみこ                  | nasuyumiko@example.com        | F      |   13 | A          | 2003/10/5 |
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
|  6 | 相川一輝        | あいかわかずき              | aikawakazuki@example.com      | M      |   35 | A          | 1981/8/18 |
|  4 | 中田英嗣        | なかたひでつぐ              | nakatahidetsugu@example.com   | M      |   23 | AB         | 1994/1/3  |
|  1 | 大村郁恵        | おおむらいくえ              | oomuraikue@example.com        | F      |   39 | B          | 1978/1/23 |
|  8 | 井口愛子        | いぐちあいこ                | iguchiaiko@example.com        | F      |   18 | B          | 1998/8/6  |
|  5 | 藤村涼子        | ふじむらりょうこ            | fujimuraryouko@example.com    | F      |   33 | O          | 1984/1/28 |
|  7 | 野崎由美子      | のざきゆみこ                | nozakiyumiko@example.com      | F      |   12 | O          | 2005/1/20 |
|  9 | 小森愛          | こもりあい                  | komoriai@example.com          | F      |   30 | O          | 1986/7/17 |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
10 rows in set (0.00 sec)
```
blood_typeの方がはじめにソートされ、それぞれのblood_typeの中でgenderがソートされていることがわかります。


## LIMITを用いて取得件数の上限を指定する。
LIMITを用いると全取得するところを指定件数以内に収めることができます。
LIMITはWHEREやORDER BYよりかは後ろに書きます。

例：年齢昇順で最大5件レコードを取得する。

```
mysql> SELECT * FROM users ORDER BY age ASC LIMIT 5;
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
| id | name            | name_kana                   | email                         | gender | age  | blood_type | birthday  |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
|  7 | 野崎由美子      | のざきゆみこ                | nozakiyumiko@example.com      | F      |   12 | O          | 2005/1/20 |
| 10 | 那須由美子      | なすゆみこ                  | nasuyumiko@example.com        | F      |   13 | A          | 2003/10/5 |
|  8 | 井口愛子        | いぐちあいこ                | iguchiaiko@example.com        | F      |   18 | B          | 1998/8/6  |
|  3 | 岡島慎之介      | おかじましんのすけ          | okajimashinnosuke@example.com | M      |   20 | O          | 1997/2/4  |
|  2 | 片岡寿明        | かたおかとしあき            | kataokatoshiaki@example.com   | M      |   21 | A          | 1995/4/21 |
+----+-----------------+-----------------------------+-------------------------------+--------+------+------------+-----------+
5 rows in set (0.00 sec)
```

「LIMIT 数字」だとただの最大件数の指定のみとなりますが、
「LIMIT 数字（aとよぶ） , 数字（bとよぶ）」とすると初めのa件だけスキップして最大b件取得するというようになります。

例：年齢昇順で初めの5件を飛ばして最大3件レコードを取得する。（つまり6~8番目を取得する。）

```
mysql> SELECT * FROM users ORDER BY age ASC LIMIT 5 ,3;
+----+--------------+--------------------------+-----------------------------+--------+------+------------+-----------+
| id | name         | name_kana                | email                       | gender | age  | blood_type | birthday  |
+----+--------------+--------------------------+-----------------------------+--------+------+------------+-----------+
|  4 | 中田英嗣     | なかたひでつぐ           | nakatahidetsugu@example.com | M      |   23 | AB         | 1994/1/3  |
|  9 | 小森愛       | こもりあい               | komoriai@example.com        | F      |   30 | O          | 1986/7/17 |
|  5 | 藤村涼子     | ふじむらりょうこ         | fujimuraryouko@example.com  | F      |   33 | O          | 1984/1/28 |
+----+--------------+--------------------------+-----------------------------+--------+------+------------+-----------+
3 rows in set (0.00 sec)
```