我有一个存储过程,它接受了几个参数。我需要根据我收到的参数值作为输入返回按特定顺序排序的结果。我面临的问题是,如果我尝试在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以及它的优缺点是什么?
答案 0 :(得分:0)
处理SELECT
变体的最佳方法是在应用程序代码中动态构造查询。
一个常见的例子是最终用户可以指定(或不指定)各种事物。应用程序可以使用指定的东西构造WHERE
子句。它甚至可以根据用户输入构造IN
或BETWEEN
子句等。
您的案例与ORDER BY
有关。同样,应用代码可以非常轻松地构建所需的ORDER BY
。这将导致有效的查询。
唉,SQL中没有构造可以替换它。