22
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【MySQL】条件をつけてソートさせる

Last updated at Posted at 2017-12-03

モニタでこの記事を見つけちゃったみんな―!はじめましてー!
初めての投稿がAdvent Calendar でちょっと緊張しているゆいもっぷだよ!
よろしくね!!

さて、テンションを落ち着かせて早速本題に入ります。

#本題
##テーブルを作ってみようと思います!
###簡単にこんなテーブルを作ります

CREATE TABLE `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
);
+----+---------+
| id | name    |
+----+---------+
|  1 | Nanako  |
|  2 | Yukari  |
|  3 | Mirai   |
|  4 | Yui     |
|  5 | Miyako  |
|  6 | Nayuta  |
|  7 | Chihiro |
|  8 | Maika   |
|  9 | Mafuyu  |
| 10 | Kaho    |
| 11 | Ginshu  |
| 12 | Ricos   |
| 13 | Yuzu    |
| 14 | Ritsu   |
| 15 | Mio     |
| 16 | Tsumugi |
| 17 | Azusa   |
| 18 | Ui      |
| 19 | Chito   |
| 20 | Yuri    |
+----+---------+

##そうなんだ、じゃあ私普通にソートさせるね
###降順でソート
とりあえずidをソートしてみます。

> SELECT * FROM test ORDER BY id DESC;

+----+---------+
| id | name    |
+----+---------+
| 20 | Yuri    |
| 19 | Chito   |
| 18 | Ui      |
| 17 | Azusa   |
| 16 | Tsumugi |
| 15 | Mio     |
| 14 | Ritsu   |
| 13 | Yuzu    |
| 12 | Ricos   |
| 11 | Ginshu  |
| 10 | Kaho    |
|  9 | Mafuyu  |
|  8 | Maika   |
|  7 | Chihiro |
|  6 | Nayuta  |
|  5 | Miyako  |
|  4 | Yui     |
|  3 | Mirai   |
|  2 | Yukari  |
|  1 | Nanako  |
+----+---------+

うんうん。

###昇順でソート
nameを昇順で並び替えてみます。

> SELECT * FROM test ORDER BY name ASC;

+----+---------+
| id | name    |
+----+---------+
| 17 | Azusa   |
|  7 | Chihiro |
| 19 | Chito   |
| 11 | Ginshu  |
| 10 | Kaho    |
|  9 | Mafuyu  |
|  8 | Maika   |
| 15 | Mio     |
|  3 | Mirai   |
|  5 | Miyako  |
|  1 | Nanako  |
|  6 | Nayuta  |
| 12 | Ricos   |
| 14 | Ritsu   |
| 16 | Tsumugi |
| 18 | Ui      |
|  4 | Yui     |
|  2 | Yukari  |
| 20 | Yuri    |
| 13 | Yuzu    |
+----+---------+

###複数のカラムをソートする

> SELECT * FROM test ORDER BY name DESC, id ASC;
+----+---------+
| id | name    |
+----+---------+
| 13 | Yuzu    |
| 20 | Yuri    |
|  2 | Yukari  |
|  4 | Yui     |
| 18 | Ui      |
| 16 | Tsumugi |
| 14 | Ritsu   |
| 12 | Ricos   |
|  6 | Nayuta  |
|  1 | Nanako  |
|  5 | Miyako  |
|  3 | Mirai   |
| 15 | Mio     |
|  8 | Maika   |
|  9 | Mafuyu  |
| 10 | Kaho    |
| 11 | Ginshu  |
| 19 | Chito   |
|  7 | Chihiro |
| 17 | Azusa   |
+----+---------+

ここまではよくみる普通のソートですね。

##条件をつけてソートする
「頭文字にRがつくnameを先頭に持ってきて、かつidを昇順にソートさせる」
といった要望があった時

> SELECT * FROM test WHERE name LIKE 'R%'
  UNION SELECT * FROM test WHERE name NOT LIKE 'R%';
+----+---------+
| id | name    |
+----+---------+
| 12 | Ricos   |
| 14 | Ritsu   |
|  1 | Nanako  |
|  2 | Yukari  |
|  3 | Mirai   |
|  4 | Yui     |
|  5 | Miyako  |
|  6 | Nayuta  |
|  7 | Chihiro |
|  8 | Maika   |
|  9 | Mafuyu  |
| 10 | Kaho    |
| 11 | Ginshu  |
| 13 | Yuzu    |
| 15 | Mio     |
| 16 | Tsumugi |
| 17 | Azusa   |
| 18 | Ui      |
| 19 | Chito   |
| 20 | Yuri    |
+----+---------+

ぱっと思いつくのがUNIONを使うやり方。

このシンプルなテーブルでシンプルな要望ならいいかもですが、
たとえば「頭文字にU, M, R がつくnameを先頭に持ってきて」(UMAじゃないよ!)
ってなった時に、

> SELECT * FROM test WHERE name LIKE 'U%' OR name LIKE 'M%' OR name LIKE 'R%'
UNION SELECT * FROM test WHERE name NOT LIKE 'U%' AND name NOT LIKE 'M%' AND name NOT LIKE 'R%';

+----+---------+
| id | name    |
+----+---------+
|  3 | Mirai   |
|  5 | Miyako  |
|  8 | Maika   |
|  9 | Mafuyu  |
| 12 | Ricos   |
| 14 | Ritsu   |
| 15 | Mio     |
| 18 | Ui      |
|  1 | Nanako  |
|  2 | Yukari  |
|  4 | Yui     |
|  6 | Nayuta  |
|  7 | Chihiro |
| 10 | Kaho    |
| 11 | Ginshu  |
| 13 | Yuzu    |
| 16 | Tsumugi |
| 17 | Azusa   |
| 19 | Chito   |
| 20 | Yuri    |
+----+---------+

と、条件が長くなり、また似たような条件が2つあるので
見るだけでゲンナリするものになっちゃいますね。

なので、これをすっきりさせるために
ORDER BY {条件式}
と書いてあげます。

こんなかんじ

> SELECT * FROM test ORDER BY name LIKE 'U%' OR name LIKE 'M%' OR name LIKE 'R%' DESC, id ASC;

だいぶスッキリしました。
ただ、これでもまだ……という感じなので、以下のように変更します。

> SELECT * FROM test ORDER BY name REGEXP '^[UMR].*' DESC, id ASC;

うん!いいね!

##なぜこういう風にできるのか
これは表示してみるとよくわかると思います。

> SELECT *, name REGEXP '^[UMR].*' AS regex FROM test ORDER BY regex DESC, id ASC;

+----+---------+-------+
| id | name    | regex |
+----+---------+-------+
|  3 | Mirai   |     1 |
|  5 | Miyako  |     1 |
|  8 | Maika   |     1 |
|  9 | Mafuyu  |     1 |
| 12 | Ricos   |     1 |
| 14 | Ritsu   |     1 |
| 15 | Mio     |     1 |
| 18 | Ui      |     1 |
|  1 | Nanako  |     0 |
|  2 | Yukari  |     0 |
|  4 | Yui     |     0 |
|  6 | Nayuta  |     0 |
|  7 | Chihiro |     0 |
| 10 | Kaho    |     0 |
| 11 | Ginshu  |     0 |
| 13 | Yuzu    |     0 |
| 16 | Tsumugi |     0 |
| 17 | Azusa   |     0 |
| 19 | Chito   |     0 |
| 20 | Yuri    |     0 |
+----+---------+-------+

条件に一致するものは1、 そうでないものは0と処理されるので、
この結果を用いてソートをかけていたということになりますね。

他にもCASE文なども使えるのでこんなソートも可能になります。

> SELECT * FROM test ORDER BY CASE WHEN name LIKE 'U%' THEN 3 WHEN name LIKE 'M%' THEN 2 WHEN name LIKE 'R%' THEN 1 ELSE 0 END DESC, id ASC;

+----+---------+------+
| id | name    | sort |
+----+---------+------+
| 18 | Ui      |    3 |
|  3 | Mirai   |    2 |
|  5 | Miyako  |    2 |
|  8 | Maika   |    2 |
|  9 | Mafuyu  |    2 |
| 15 | Mio     |    2 |
| 12 | Ricos   |    1 |
| 14 | Ritsu   |    1 |
|  1 | Nanako  |    0 |
|  2 | Yukari  |    0 |
|  4 | Yui     |    0 |
|  6 | Nayuta  |    0 |
|  7 | Chihiro |    0 |
| 10 | Kaho    |    0 |
| 11 | Ginshu  |    0 |
| 13 | Yuzu    |    0 |
| 16 | Tsumugi |    0 |
| 17 | Azusa   |    0 |
| 19 | Chito   |    0 |
| 20 | Yuri    |    0 |
+----+---------+------+

##まとめ
これで色々なソートができるようになりました!
書きたいことを書いてしまってすごく散らかってしまったこの記事も、上手くソートできたらいいんですけどね!

22
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?