MySQL ORDER BY随机字段不适用于其他操作

时间:2015-08-10 12:54:57

标签: mysql sql

我面对MySQL的奇怪行为。当我选择一个在计算中使用RAND()的字段并按此字段对结果进行排序时,一切正常:

SELECT 
RAND() AS r
FROM SomeTable
ORDER BY r DESC;

但是,如果我在ORDER BY子句中执行其他操作,例如+, - ,*。 /或者对于常量或其他字段,无论您喜欢什么,结果都不再排序。例如:

SELECT 
RAND() AS r
FROM SomeTable
ORDER BY r+1 DESC;

当然我可以在另外一个领域移动操作,但我只是好奇我是否做错了。我假设由于某些未知原因,如果在ORDER BY子句中执行某些操作,MySQL将重新评估该字段。

这是一个正确的假设吗?

2 个答案:

答案 0 :(得分:2)

MySQL 5.0 Reference

  

您不能在ORDER BY子句中使用具有RAND()值的列,   因为ORDER BY会多次评估该列。

每次调用

RAND()时都会对其进行评估,即使您将其别名为r,它也会被重新评估,并且不会与列保持相同的值

如果你想ORDER BY r+1,你需要一个子查询:

SELECT *
FROM (SELECT col1, RAND() AS r
      FROM Table1
      ) sub
ORDER BY (r+1) DESC;

答案 1 :(得分:0)

问题似乎是由其他数据库称为“volatile”函数和MySQL称为“非确定性”函数引起的。这些函数在每次调用时都会返回不同的值。

根据您的观察,您的第二个查询将被评估为:

SELECT RAND() AS r
FROM SomeTable
ORDER BY RAND() + 1 DESC;

也就是说,r表达式正在插入ORDER BY。因为rand()是非确定性的,所以每次调用它时都会返回不同的值。结果是随机排序的结果集,但不同于r列的排序。

在我看来,这是MySQL中的一个错误它正在使用表达式替换为(或至少应该)声明为NOT DETERMINISTIC的函数。 “bug”可能只是内置的rand()函数未正确声明为not deterministic。声明可能会被忽略。显然,MySQL应该使用别名引用的值,而不是表达式,尤其是对于非确定性函数。

注意:除了确定性功能之外,这还有潜在的影响。如果表达式是一个复杂,耗时的表达式,它最终可能会被order by多次评估。