我面对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将重新评估该字段。
这是一个正确的假设吗?
答案 0 :(得分:2)
每次调用您不能在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
多次评估。