ああ、やっぱり今回もダメだったよ。あいつは自然順でソートしてくれないからな。

この記事はだいぶ前に書かれたものなので情報が古いかもしれません

あいつってのはMySQLのことです。



あいつを使ってレコードを取得する際、ソートをしたいと思ったらORDER BY句を使いますよね。そこまでは良い。

でも、そのソートの対象がvarchar型だったりしたときに、単純にASCだのDESCだのしても、思う通りの順番でソートできないことがある。

//sample_table
+----+-----------+
| id | unique_id |
+----+-----------+
|  1 |     A1    |
|  2 |     A2    |
|  3 |     A3    |
|  4 |     A4    |
|  5 |     A5    |
|  6 |     A6    |
|  7 |     A7    |
|  8 |     A8    |
|  9 |     A9    |
| 10 |    A10    |
+----+-----------+

こんな感じのレコードを、unique_idの方でソートしてみましょう。

//発行するSQL
SELECT * FROM sample_table ORDER BY unique_id ASC



ルシフェルさん「おい、そんなソートで大丈夫か?」

MySQL「大丈夫だ。問題ない」



//結果
+----+-----------+
| id | unique_id |
+----+-----------+
|  1 |     A1    |
| 10 |    A10    |
|  2 |     A2    |
|  3 |     A3    |
|  4 |     A4    |
|  5 |     A5    |
|  6 |     A6    |
|  7 |     A7    |
|  8 |     A8    |
|  9 |     A9    |
+----+-----------+

はい、ダメでしたー。

varchar型とかは文字列の型だから、A1とかA10がただの文字列として扱われてしまうんですな。数字の部分が数値として扱われない。だからA10の方がA2よりも前になってしまう。

例えばこれがPHPの配列だったら、natsortっていう、自然順にソートしてくれるやつがあるんで、それ使ってソートすれば良い。自然順っていうのは、単純に文字列でのソートと違って、人が一般的にやりそうな感じにソートする方法です。だからA2よりもA10の方が先に来ることはない。ちゃんとA1からA10まで順番に並んでくれる。

じゃあそのPHPでいうnatsortと同じような機能が、MySQLにはないのかと言うと……。



ないです(ToT)



たぶんですけどね。もしあるならぜひ教えてほしいです。

上記の例みたいに、数字の前にはアルファベットが1文字だけしかつかないとか、そういう限定的な条件がつくような場合なら、CASTとかいう関数を使ったりしてやれないことはないっぽいんですが、もっと複雑な場合、例えばそうね……ユーザーさんが自分で適当に決められるログインIDとかの場合は、数字とアルファベットがどんな風に混ざってくるか分からないから、単純にCASTとかで何とかするってわけにはいかないと思う。

ちなみに「CASTってどんな関数?」っていう疑問をお持ちの方。

「神は言っている。ここで知るさだめではないと」

ようするに「この記事を書いている人はCASTを使ったことがないからよく分かっていないのでググるがよろしい」って言っているわけですね、神は。すみませんがここは一つ、神の言う通りにしてください。



そういうわけなので、僕も今回、どうしても自然順のソートでデータを取得する方法が必要だったんですが、結局できないらしいってことが分かったので、あきらめました。

もう一つ別にカラムを用意して、新規にレコードが追加されたり編集されたりするたびに、裏側でこっそり一度全データを取得して、PHP側で自然順にソートして、その順番を用意したカラムに入れて、そっちでORDER BYするっていう、そんな感じになってしまいました。まあ仕方ないっすね。

こういう、自然順でソートしたいっていう需要は、かなりあると思うんだけど、MySQLの開発者の人たちはそれを実装しようとは思わないのかな。実装がかなり難しいのかな……?

匿名 2013年07月09日 13:08:42
単純関数で良い感じに作ってそれで並び替えするとかしか思いつかないですね・・・・
まっち~(管理人) 2013年07月10日 10:37:33
>匿名さん
あ〜……やっぱりそうなんですか。致し方ないってことですね。
バージョンアップが繰り返される中で、いずれその辺も実装されることを夢見て待つことにします。
もしかしたら何か関連しているかも?