Comme mentionné dans La version MySQL 8.0.0 Milestone est disponible ,
Je suppose que c'est la cause du comportement que j'observe dans les nouvelles versions de MySQL. L'astuce mentionnée peut être utilisée avec MySQL 8.0 pour forcer RAND() à n'être appelé qu'une seule fois :
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 |
+---+-----+-----+
Ceci n'est cependant pas disponible dans 5.7. Pour obtenir le comportement souhaité avec 5.7, ajoutez LIMIT <a very high number>
à la définition de la table dérivée (j'utilise signé LONG_MAX ci-dessous). Merci à Roy Lyseng pour cette solution de contournement
.
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 |
+---+-----+-----+
En tant que philippie mentionné dans le commentaire, le résultat d'une expression de requête doit être strictement défini quelles que soient les optimisations appliquées. Ce qui signifie qu'il s'agit d'un bogue d'optimisation dans MySQL 5.7/8.0.