MySql:如何处理条件排序

时间:2016-10-19 09:33:08

标签: mysql innodb

我有一个存储过程,它接受了几个参数。我需要根据我收到的参数值作为输入返回按特定顺序排序的结果。我面临的问题是,如果我尝试在order by子句中使用switch-case块编写单个查询,则查询不会使用任何索引。样本结构如下所示


create table test_table(
f1 int,
f2 int,
f3 int,
key (f1),
key(f2)
);

-- now insert 2M rows in the table

-- query #1
mysql> explain select f1, f2 from test_table order by f1 desc limit 1000;
+----+-------------+------------+-------+---------------+------+---------+------+------+-------+
| id | select_type | table      | type  | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+------------+-------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | test_table | index | NULL          | f1   | 5       | NULL | 1000 | NULL  |
+----+-------------+------------+-------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

-- query #2
mysql> explain select f1, f2 from test_table order by f2 desc limit 1000;
+----+-------------+------------+-------+---------------+------+---------+------+------+-------+
| id | select_type | table      | type  | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+------------+-------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | test_table | index | NULL          | f2   | 5       | NULL | 1000 | NULL  |
+----+-------------+------------+-------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

set @a = 1, @b = 'd';

--query #3
mysql> explain select f1, f2 from test_table
   order by
    case when @a = 1 and @b = 'd' then f1
         when @a = 2 and @b = 'd' then f2 end desc,
    case when @a = 1 and @b = 'a' then f1
         when @a = 2 and @b = 'a' then f2 end asc
      limit 1000;
+----+-------------+------------+------+---------------+------+---------+------+---------+----------------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows    | Extra          |
+----+-------------+------------+------+---------------+------+---------+------+---------+----------------+
|  1 | SIMPLE      | test_table | ALL  | NULL          | NULL | NULL    | NULL | 1995435 | Using filesort |
+----+-------------+------------+------+---------------+------+---------+------+---------+----------------+
1 row in set (0.00 sec)

如果您看到查询1或查询2,则解释输出符合预期。但是当我尝试在运行时决定排序列时,它不能使用任何索引。实现#3的另一种方法是编写if-else块并在那里编写单独的查询,但如果有多种可能性,它将变得丑陋。在上面的例子中,它将导致4个类似的块具有不同的order by子句

我的问题: 是否有另一种方法可以完成查询#3以及它的优缺点是什么?

1 个答案:

答案 0 :(得分:0)

处理SELECT变体的最佳方法是在应用程序代码中动态构造查询。

一个常见的例子是最终用户可以指定(或不指定)各种事物。应用程序可以使用指定的东西构造WHERE子句。它甚至可以根据用户输入构造INBETWEEN子句等。

您的案例与ORDER BY有关。同样,应用代码可以非常轻松地构建所需的ORDER BY。这将导致有效的查询。

唉,SQL中没有构造可以替换它。