mysqlのorder by fieldで指定のID順に並べる

どういった時に使うんだよwwwって思いましたが、使う感じになりました。

select *
  from icons
 where id in(4, 5, 6)
 order by field(id, 5, 4, 6)

=>
mysql> select * from icons where id in(4, 5, 6) order by field(id, 5, 4, 6);
+----+------------------+-----------------+--------------------+-----------------+---------------------+---------------------+---------------------+
| id | icon_category_id | image_file_name | image_content_type | image_file_size | image_updated_at    | created_at          | updated_at          |
+----+------------------+-----------------+--------------------+-----------------+---------------------+---------------------+---------------------+
|  5 |                1 | 1f606.png       | image/png          |            2277 | 2017-03-13 15:09:17 | 2017-03-13 15:09:17 | 2017-03-19 00:50:29 |
|  4 |                1 | 1f601.png       | image/png          |            2235 | 2017-03-13 15:09:17 | 2017-03-13 15:09:17 | 2017-03-19 00:50:29 |
|  6 |                1 | 1f605.png       | image/png          |            2685 | 2017-03-13 15:09:17 | 2017-03-13 15:09:17 | 2017-03-19 00:50:29 |
+----+------------------+-----------------+--------------------+-----------------+---------------------+---------------------+---------------------+

確かに順番通りに返ってくる。

https://dev.mysql.com/doc/refman/5.6/ja/string-functions.html#function_field

FIELD(str,str1,str2,str3,…)

str1、str2、str3、… リスト内で str のインデックス (位置) を返します。str が見つからない場合は、0 を返します。

FIELD() へのすべての引数が文字列の場合は、すべての引数が文字列として比較されます。すべての引数が数値の場合は、数字として比較されます。それ以外の場合は、引数が倍精度として比較されます。

NULL ではどの値との等価比較にも失敗するため、str が NULL である場合は、戻り値が 0 になります。FIELD() は ELT() の補数です。

FIELD関数を使用しているってことなのね。

railsで使う場合

ids = [5, 4, 6]
Icon.where(id: ids).order("field(id, #{ids.join(',')})")

orderの中で文字列展開をして、使用しているってことですね。

rails5からはキチンとしたmethodがあるようです。

以上です。

参考

qiita.com

yoku0825.blogspot.jp