MySQL 中的 ORDER BY FIELD() 如何在内部工作

itz*_*nsn 52 mysql order-by fields

我了解ORDER BY子句的工作原理以及FIELD()函数的工作原理。我想了解的是他们两个如何一起工作进行排序。如何检索行以及如何导出排序顺序

+----+---------+
| id |  name   |
+----+---------+
|  1 | stan    |
|  2 | kyle    |
|  3 | kenny   |
|  4 | cartman |
+----+---------+ 

SELECT * FROM mytable WHERE id IN (3,2,1,4) ORDER BY FIELD(id,3,2,1,4)
Run Code Online (Sandbox Code Playgroud)

上面的查询将导致

+----+---------+
| id |  name   |
+----+---------+
|  3 | kenny   |
|  2 | kyle    |
|  1 | stan    |
|  4 | cartman |
+----+---------+ 
Run Code Online (Sandbox Code Playgroud)

类似于说 ORDER BY 3, 2, 1, 4

问题

  • 这在内部如何运作?
  • MySQL如何获取行,并计算排序顺序?
  • MySQL 如何知道它必须按 id 列排序?

Rol*_*DBA 86

作为记录

SELECT * FROM mytable WHERE id IN (1,2,3,4) ORDER BY FIELD(id,3,2,1,4);
Run Code Online (Sandbox Code Playgroud)

应该也能工作,因为您不必在WHERE子句中对列表进行排序

至于它是如何运作的,

  • FIELD()是一个函数,如果您要搜索的值存在,它会返回逗号分隔列表的索引位置。

  • 这些ORDER BY值由FIELD()返回的内容评估

您可以创建各种花哨的订单

例如,使用IF()函数

SELECT * FROM mytable
WHERE id IN (1,2,3,4)
ORDER BY IF(FIELD(id,3,2,1,4)=0,1,0),FIELD(id,3,2,1,4);
Run Code Online (Sandbox Code Playgroud)

这将导致前 4 个 id 出现在列表顶部,否则,它出现在底部。为什么?

在 中ORDER BY,你要么得到 0,要么得到 1。

  • 如果第一列是 0,则显示前 4 个 ID 中的任何一个
  • 如果第一列是 1,让它出现在后面

让我们用第一列中的 DESC 翻转它

SELECT * FROM mytable
WHERE id IN (1,2,3,4)
ORDER BY IF(FIELD(id,3,2,1,4)=0,1,0) DESC,FIELD(id,3,2,1,4);
Run Code Online (Sandbox Code Playgroud)

在 中ORDER BY,您仍然会得到 0 或 1。

  • 如果第一列是 1,则显示前 4 个 ID 以外的任何内容。
  • 如果第一列是 0,则使前 4 个 id 以原始顺序出现

您的实际问题

如果您真的想要了解内部结构,请转到本书的第 189 页和第 192 页

MySQL 内部结构

真正的深潜。

本质上,有一个 C++ 类称为ORDER *orderORDER BY表达式树)。在JOIN::prepare,*order用于名为 的函数中setup_order()为什么在JOIN课堂中间? 每个查询,甚至是针对单个表的查询总是作为 JOIN 处理(请参阅我的帖子JOIN 条件和 WHERE 条件之间是否存在执行差异?

所有这些的源代码是 sql/sql_select.cc

显然,这ORDER BY棵树将持有 的评估FIELD(id,3,2,1,4)。因此,数字 0,1,2,3,4 是被排序的值,同时携带对相关行的引用。

  • 这是一个非常出色的解释。使用这些方法我能够得到 3 个订单,一个主要的第一个值是集合的最大值,然后是 FIELD,然后是另一个列,用于不在 FIELD 集中的那些。我以前做梦都想不到的事情。感谢您花时间真正解释这实际上是如何工作的。 (3认同)