てきとうなさいと べぇたばん

SQLで任意の順番でソートする

ORDER BY

メモ。SQLで、任意の順番でソートしたい時がある。

CASE式

CASE式を使う。以下のSQLはとりあえずemployeeというテーブルがあって、「3,9,1,8」の順に並べたいとしている。

SELECT id, name
  FROM employee
 WHERE id IN (3, 9, 1, 8)
 ORDER BY CASE id WHEN 3 THEN 1
                  WHEN 9 THEN 2
                  WHEN 1 THEN 3
                  WHEN 8 THEN 4
                  END ASC;

なぜWHEREがあるのか、以下のようにLIMITで絞ればいいじゃないかと考えることもあった。

SELECT id, name
  FROM employee
 ORDER BY CASE id WHEN 3 THEN 1
                  WHEN 9 THEN 2
                  WHEN 1 THEN 3
                  WHEN 8 THEN 4
                  ELSE 9999 END ASC
 LIMIT 4;

EXPLAINなどで2つのクエリの動作をみてみる。

mysql> EXPLAIN SELECT id, name
    ->   FROM employee
    ->  WHERE id IN (3, 9, 1, 8)
    ->  ORDER BY CASE id WHEN 3 THEN 1
    ->                   WHEN 9 THEN 2
    ->                   WHEN 1 THEN 3
    ->                   WHEN 8 THEN 4
    ->                   END ASC;
+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------+
| id | select_type | table    | type  | possible_keys | key     | key_len | ref  | rows | Extra                       |
+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------+
|  1 | SIMPLE      | employee | range | PRIMARY       | PRIMARY | 4       | NULL |    4 | Using where; Using filesort |
+----+-------------+----------+-------+---------------+---------+---------+------+------+-----------------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT id, name
    ->   FROM employee
    ->  ORDER BY CASE id WHEN 3 THEN 1
    ->                   WHEN 9 THEN 2
    ->                   WHEN 1 THEN 3
    ->                   WHEN 8 THEN 4
    ->                   ELSE 9999 END ASC
    ->  LIMIT 4;
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra          |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+
|  1 | SIMPLE      | employee | ALL  | NULL          | NULL | NULL    | NULL |    9 | Using filesort |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------+

ここでわかったのは、LIMITではテーブルのすべてのデータを読み取るので、そこからソートするので遅い、という解釈でいいのかな。