如何在MySQL中定义自定义ORDER BY顺序


142

在MySQL中,如何定义自定义排序顺序。

为了尝试解释我想要考虑的表,请执行以下操作:

ID  Language    Text
0   ENU         a
0   JPN         b
0   DAN         c       
1   ENU         d
1   JPN         e
1   DAN         f
2   etc...

在这里,我想返回按语言和升序ID排序的所有行,以便首先出现Language = ENU,然后是JPN,最后是DAN。

结果应为:a,d,b,e,c,f等。

这有可能吗?

Answers:


274

MySQL有一个方便的函数FIELD(),它非常适合执行此类任务。

ORDER BY FIELD(Language,'ENU','JPN','DAN'), ID

但是请注意,

  1. 由于其他DBMS可能没有此功能,因此它使SQL的可移植性较差

  2. 当您的语言列表(或其他要排序的值)长得多时,最好有一个带有sortorder列的单独表,然后将其加入查询中进行排序。


3
正是由于这种情况,我才需要对两个值进行排序(一种主要语言,例如JPN,一种后备语言,例如ENU)。
Muleskinner

4
伙计,您刚刚救了我一个magento重写:)
Erik Simonic 2015年

1
如果您GROUP BY之前有过该怎么办?例如,我想要的第一个值出现在末尾?
Pathros,2015年

将查询放入GROUP BY子查询中,并在外部查询中对其进行排序
Mchl,2015年

1
像魅力一样工作:)
Brane 2015年

53

如果这些是仅有的三个值,那么你可以使用一个CASE表达式

ORDER BY `ID`,
         CASE `Language`
         WHEN 'ENU' THEN 1
         WHEN 'JPN' THEN 2
         WHEN 'DAN' THEN 3
         END

(如果可能还有其他值,那么您可能想要添加一些额外的逻辑以保持顺序一致;例如,您可以添加ELSE 4到该CASE表达式,然后将Language其本身作为第三个排序标准:

ORDER BY `ID`,
         CASE `Language`
         WHEN 'ENU' THEN 1
         WHEN 'JPN' THEN 2
         WHEN 'DAN' THEN 3
         ELSE 4
         END,
         `Language`


1
而如果有许多语言值,你可以有一个单独的表存储每种语言加上一个排序顺序列,并链接到
凯伊

1
这将首先通过ID进行排序,从而导致a,b,c,d,e,f
piotrm 2012年

由于该工程完美-象我接受,因为它看起来简单MCHL答案
Muleskinner

19

您有两个选择,第一个是将Language更改为ENUM(假设这是可能的,并且您只希望有一些变化)

如果指定其为ENUM('ENU','JPN','DAN')随后ORDER Language ASC将订购您指定的顺序。

第二个将涉及某个地方的案例,即

SELECT * FROM table
ORDER BY CASE Language
    WHEN 'ENU' THEN 3
    WHEN 'JPN' THEN 2
    WHEN 'DAN' THEN 1
    ELSE 0
END DESC, ID ASC

在性能方面,ENUM方法将返回更快的结果,但是如果您需要添加更多的语言,则将更加麻烦。第三种选择是为语言添加一个规范化表,但是在这种情况下可能会显得过大。


您在哪里键入ENUM('ENU','JPN','DAN')
Pathros,2015年

1
在表定义中@pathros,您将其指定为ENUM而不是VARCHAR等。MySQL在内部以特定顺序存储ENUM选项并为其建立索引,因此,当按ENUM列进行排序时,它将特别使用该内部索引而不是字符串值(除非使用CAST()将其返回到VARCHAR)
我的学校网站Simon在

END DESC,应该END CASE DESC,吗?
Istiaque Ahmed

不。并非所有CASE需求都END CASE取决于上下文。 CASE在PROCEDURE中,需要END CASEdev.mysql.com/doc/refman/5.5/en/case.html),但是CASE在SELECT中不需要END CASE,只需ENDdev.mysql.com/doc/refman/5.7/en/…)- 在此上下文是控制流功能。
西蒙(My Simon)在我学校的门户网站上,

1

对于Yii2框架,我们可以通过以下方式实现

Project::find()
->orderBy([new Expression('FIELD(pid_is_t_m,2,0,1)'),'task_last_work'=> SORT_ASC])
->all();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.