Como se menciona en El lanzamiento de MySQL 8.0.0 Milestone está disponible ,
Supongo que esta es la causa del comportamiento que estoy observando en las versiones más nuevas de MySQL. La sugerencia mencionada se puede usar con MySQL 8.0 para forzar que RAND() se llame solo una 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 |
+---+-----+-----+
Sin embargo, esto no está disponible en 5.7. Para lograr el comportamiento deseado con 5.7, agregue LIMIT <a very high number>
a la definición de la tabla derivada (estoy usando LONG_MAX firmado a continuación). Gracias a Roy Lyseng por esta solución 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 en el comentario, el resultado de una expresión de consulta debe definirse estrictamente independientemente de las optimizaciones que se apliquen. Lo que significa que es un error del optimizador en MySQL 5.7/8.0.