RAND

La función RAND genera un número aleatorio de punto flotante entre 0 (inclusive) y 1 (exclusive). Es decir, puede devolver 0.0 pero nunca 1.0. Cada vez que la ejecutas, obtienes un valor diferente.

Aunque generar un número entre 0 y 1 puede parecer limitado, a partir de ese valor puedes crear números aleatorios en cualquier rango, seleccionar filas al azar, mezclar resultados, generar datos de prueba y mucho más.

Sintaxis

-- Número aleatorio diferente en cada ejecución
RAND()
 
-- Número aleatorio reproducible (con semilla)
RAND(semilla)

Sin argumentos, RAND() usa una semilla interna que cambia con cada ejecución, garantizando valores diferentes. Con una semilla fija, siempre produce la misma secuencia de números, lo cual es útil para pruebas reproducibles.

Comportamiento básico

SELECT RAND() AS aleatorio;
aleatorio
0.7342859135

Si ejecutas esta consulta varias veces, obtendrás un valor diferente cada vez. El valor siempre estará entre 0.000... y 0.999..., con muchos decimales de precisión.

Múltiples valores aleatorios

Cada llamada a RAND() en la misma consulta produce un valor diferente:

SELECT RAND() AS primero, RAND() AS segundo, RAND() AS tercero;
primerosegundotercero
0.1234...0.5678...0.9012...

Los tres valores serán diferentes entre sí y diferentes en cada ejecución.

Generar números en un rango específico

El valor entre 0 y 1 que devuelve RAND() es solo el punto de partida. Con un poco de aritmética, puedes generar números en cualquier rango:

Entero entre 1 y N

La fórmula general es FLOOR(RAND() * N) + 1:

-- Simular un dado de 6 caras
SELECT FLOOR(RAND() * 6) + 1 AS dado;

¿Cómo funciona? RAND() da un valor entre 0 y 0.999..., multiplicado por 6 da entre 0 y 5.999..., FLOOR lo convierte en un entero entre 0 y 5, y sumando 1 obtienes entre 1 y 6.

-- Entero entre 1 y 100
SELECT FLOOR(RAND() * 100) + 1 AS numero;
 
-- Entero entre 50 y 150
SELECT FLOOR(RAND() * 101) + 50 AS numero;

La fórmula general para un entero entre min y max (ambos inclusivos) es:

FLOOR(RAND() * (max - min + 1)) + min

Decimal en un rango

Para decimales no necesitas FLOOR:

-- Decimal entre 10.00 y 50.00
SELECT ROUND(RAND() * 40 + 10, 2) AS precio_aleatorio;

RAND() * 40 da entre 0 y 39.99..., sumando 10 obtienes entre 10.00 y 49.99..., y ROUND ajusta a 2 decimales.

Seleccionar filas al azar

El uso más popular de RAND() en MySQL es seleccionar filas aleatorias de una tabla. La técnica es usar ORDER BY RAND(), que asigna un número aleatorio a cada fila y luego ordena por ese número:

SELECT nombre, precio
FROM productos
ORDER BY RAND()
LIMIT 3;

Cada ejecución devuelve 3 productos diferentes (o al menos en distinto orden). Esto es útil para mostrar productos destacados aleatorios, sugerencias, preguntas de un quiz, etc.

El problema de rendimiento

ORDER BY RAND() tiene un problema serio de rendimiento en tablas grandes. Para ordenar aleatoriamente, MySQL tiene que:

  1. Generar un número aleatorio para cada fila de la tabla
  2. Ordenar todas las filas por ese número
  3. Devolver solo las primeras N

Si tu tabla tiene 1 millón de filas y quieres 5 al azar, MySQL genera 1 millón de números aleatorios, ordena 1 millón de filas, y luego descarta 999.995. Es tremendamente ineficiente.

Para tablas pequeñas (cientos o pocos miles de filas), no hay problema. Para tablas grandes, necesitas una alternativa.

Alternativa eficiente para tablas grandes

Si la tabla tiene IDs numéricos consecutivos (o casi consecutivos), puedes generar un ID aleatorio directamente:

-- Seleccionar 1 fila aleatoria eficientemente
SELECT * FROM productos
WHERE id >= FLOOR(RAND() * (SELECT MAX(id) FROM productos)) + 1
ORDER BY id
LIMIT 1;

Esta consulta genera un único número aleatorio (no millones) y busca la fila con el ID más cercano. Es enormemente más rápido, aunque puede sesgar ligeramente hacia filas con IDs más altos si hay huecos en la secuencia.

Otra alternativa para seleccionar múltiples filas aleatorias sin ORDER BY RAND():

-- Seleccionar 5 filas aleatorias usando subconsulta
SELECT * FROM productos
WHERE id IN (
    SELECT FLOOR(RAND() * (SELECT MAX(id) FROM productos)) + 1
    FROM productos LIMIT 5
);

RAND con semilla (resultados reproducibles)

Si pasas un argumento a RAND(), se usa como semilla del generador de números pseudoaleatorios. La misma semilla siempre produce la misma secuencia de números:

SELECT RAND(42) AS primero, RAND() AS segundo;

Si ejecutas esto varias veces, primero siempre tendrá el mismo valor (porque la semilla 42 siempre inicia la misma secuencia). segundo será diferente en cada ejecución porque no tiene semilla fija.

Las semillas fijas son útiles para:

  • Pruebas reproducibles: cuando necesitas que un test siempre genere los mismos datos aleatorios
  • Depuración: cuando un bug ocurre con ciertos datos aleatorios y necesitas reproducirlo
  • Demostraciones: cuando quieres que una demo muestre siempre los mismos resultados

Caso práctico: generar datos de prueba

RAND es muy útil para poblar tablas con datos de prueba realistas:

-- Generar precios aleatorios entre 10 y 1000 con 2 decimales
SELECT ROUND(RAND() * 990 + 10, 2) AS precio_aleatorio;
 
-- Generar stock aleatorio entre 0 y 200
SELECT FLOOR(RAND() * 201) AS stock_aleatorio;
 
-- Generar una fecha aleatoria en los últimos 365 días
SELECT DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 365) DAY) AS fecha_aleatoria;

Caso práctico: asignar descuentos aleatorios

En campañas de marketing tipo "ruleta de descuentos", puedes asignar descuentos aleatorios a los clientes:

SELECT
    nombre,
    precio,
    FLOOR(RAND() * 4 + 1) * 5 AS descuento_pct
FROM productos
LIMIT 5;

FLOOR(RAND() * 4 + 1) genera un entero entre 1 y 4, multiplicado por 5 da descuentos de 5%, 10%, 15% o 20%. Cada producto (o cada ejecución) obtiene un descuento aleatorio diferente.

Consideraciones de seguridad

RAND() usa un generador de números pseudoaleatorios (PRNG). Esto significa que los números no son verdaderamente aleatorios, sino que se calculan mediante un algoritmo determinista a partir de una semilla. Para la mayoría de usos (selección aleatoria, datos de prueba, sorteos simples) esto es perfectamente adecuado.

Sin embargo, no uses RAND() para generar valores de seguridad como:

  • Contraseñas o tokens de autenticación
  • Claves de cifrado
  • Identificadores de sesión
  • Tokens de reseteo de contraseña

Para esos casos, MySQL ofrece la función RANDOM_BYTES() que genera bytes criptográficamente seguros, o mejor aún, genera los valores de seguridad en tu aplicación usando las funciones criptográficas del lenguaje de programación.

Con esto completamos la sección de funciones numéricas. En la siguiente sección exploraremos las funciones de fecha en MySQL.

Escrito por Eduardo Lázaro