以预定义的顺序返回查询结果

时间:2020-03-06 14:43:54  来源:igfitidea点击:

是否有可能以预定顺序执行SELECT语句,即选择ID 7,2,5,9和8并以该顺序返回它们,仅基于ID字段?

语句SELECT id FROM table WHERE id in(7,2,5,9,8);和SELECT id FROM table WHERE id in(8,2,5,9,7);两者都以相同的顺序返回。

解决方案

所有排序都由ORDER BY关键字完成,但是我们只能按升序和降序排序。如果我们使用的是PHP之类的语言,则可以使用一些代码对它们进行相应的排序,但是我认为单独使用MySQL是不可能的。

这在Oracle中有效。我们可以在MySql中做类似的事情吗?

SELECT ID_FIELD
FROM SOME_TABLE
WHERE ID_FIELD IN(11,10,14,12,13)
ORDER BY
  CASE WHEN ID_FIELD = 11 THEN 0
       WHEN ID_FIELD = 10 THEN 1
       WHEN ID_FIELD = 14 THEN 2
       WHEN ID_FIELD = 12 THEN 3
       WHEN ID_FIELD = 13 THEN 4
  END

我们能否包含一个将ID 7、2、5,...映射到普通的1、2、3,...然后通过该表达式排序的case表达式?

我不认为这是可能的,但是在这里找到了一个博客条目,似乎可以满足需求:

SELECT id FROM table WHERE id in (7,2,5,9,8) 
ORDER BY FIND_IN_SET(id,"7,2,5,9,8");

将给不同的结果

SELECT id FROM table WHERE id in (7,2,5,9,8) 
ORDER BY FIND_IN_SET(id,"8,2,5,9,7");

FIND_IN_SET返回第二个参数中id的位置,因此对于上面的第一种情况,id的7在集合中的位置1在2处在2,依此类推mysql内部计算出类似

id | FIND_IN_SET
---|-----------
7  | 1
2  | 2
5  | 3

然后按" FIND_IN_SET"的结果排序。

我们可能需要创建一个带有自动编号字段的临时表,并以所需的顺序插入到该表中。然后在新的自动编号字段上排序。

它很hacky(可能很慢),但是我们可以通过UNION ALL获得效果:

SELECT id FROM table WHERE id = 7
UNION ALL SELECT id FROM table WHERE id = 2
UNION ALL SELECT id FROM table WHERE id = 5
UNION ALL SELECT id FROM table WHERE id = 9
UNION ALL SELECT id FROM table WHERE id = 8;

编辑:其他人提到了find_in_set函数,该函数在此处记录。

我能想到的最好的方法是添加第二个Column orderColumn:

7 1
2 2
5 3
9 4 
8 5

然后只需执行ORDER BY orderColumn

嗯,不是真的。我们可以获得的最接近的可能是:

SELECT * FROM table WHERE id IN (3, 2, 1, 4) ORDER BY id=4, id=1, id=2, id=3

但是你可能不想要那个:)

如果没有关于表中内容的更多信息,很难为我们提供任何更具体的建议。

ORDER BY FIELD(ID,7,2,4,5,8)是我们最好的选择,但它仍然很难看。

我们可以在这里快速得到答案,不是吗

我问这个问题的原因是,这是我想到避免对复杂的多维数组进行排序的唯一方法。我并不是说很难进行排序,但是如果有一种简单的方法可以对直接sql进行排序,那为什么不呢。

一种Oracle解决方案是:

SELECT id FROM table WHERE id in (7,2,5,9,8)
ORDER BY DECODE(id,7,1,2,2,5,3,9,4,8,5,6);

这会为每个ID分配一个订单号。可以正常使用一小部分值。