Conforme mencionado em A versão do marco do MySQL 8.0.0 está disponível ,
Suponho que esta seja a causa do comportamento que estou observando nas versões mais recentes do MySQL. A dica mencionada pode ser usada com o MySQL 8.0 para forçar RAND() a ser chamado apenas uma vez:
SELECT /* NO_MERGE(q) */
q.i,
q.r,
q.r
FROM (
SELECT
id AS i,
(FLOOR(RAND(100) * 4)) AS r
FROM t
) AS q;
+---+-----+-----+
| i | r | r |
+---+-----+-----+
| 1 | 0 | 0 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
| 4 | 2 | 2 |
| 5 | 1 | 1 |
+---+-----+-----+
Isso, no entanto, não está disponível em 5.7. Para obter o comportamento desejado com 5.7, adicione
LIMIT <a very high number>
para a definição da tabela derivada (estou usando LONG_MAX assinado abaixo). Obrigado a Roy Lyseng por esta solução alternativa
. SELECT
q.i,
q.r,
q.r
FROM (
SELECT
id AS i,
(FLOOR(RAND(100) * 4)) AS r
FROM t LIMIT 9223372036854775807
) AS q;
+---+-----+-----+
| i | r | r |
+---+-----+-----+
| 1 | 0 | 0 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
| 4 | 2 | 2 |
| 5 | 1 | 1 |
+---+-----+-----+
Como philipxy mencionado no comentário, o resultado de uma expressão de consulta deve ser estritamente definido, independentemente de quaisquer otimizações aplicadas. O que significa que é um bug do otimizador no MySQL 5.7/8.0.