VARIANCE

La función VARIANCE calcula la varianza poblacional de un conjunto de valores numéricos. La varianza es una medida de dispersión que indica cuánto se alejan los valores individuales de la media del grupo. Matemáticamente, es el cuadrado de la desviación estándar: si STD devuelve 10, VARIANCE devuelve 100. Aunque la desviación estándar es más intuitiva (se expresa en las mismas unidades que los datos), la varianza tiene propiedades matemáticas que la hacen útil en análisis más avanzados, como la descomposición de la variabilidad total en componentes.

MySQL ofrece dos sinónimos: VARIANCE y VAR_POP. Ambos calculan exactamente lo mismo: la varianza poblacional, que divide la suma de los cuadrados de las diferencias por N (el número total de valores).

Sintaxis

VARIANCE(expresion)
VAR_POP(expresion)

La fórmula que aplica MySQL es:

VARIANCE = SUM((x - media)^2) / N

Donde x es cada valor, media es el promedio y N es el número de valores no nulos. Observa que esta fórmula es equivalente a elevar al cuadrado el resultado de STD.

Comportamiento básico

Veamos la varianza de los precios de todos los productos y su relación con la desviación estándar:

SELECT
    ROUND(AVG(precio), 2) AS precio_medio,
    ROUND(VARIANCE(precio), 2) AS varianza,
    ROUND(STD(precio), 2) AS desviacion_estandar,
    ROUND(SQRT(VARIANCE(precio)), 2) AS raiz_varianza
FROM productos;
precio_mediovarianzadesviacion_estandarraiz_varianza
384.52183757.41428.67428.67

La raíz cuadrada de la varianza (183757.41) es exactamente la desviación estándar (428.67). Esto confirma la relación directa entre ambas funciones. La varianza tiene un valor mucho más grande porque está expresada en unidades al cuadrado (euros al cuadrado, en este caso), lo que la hace menos intuitiva para interpretar directamente.

Caso práctico: comparar homogeneidad entre categorías

La varianza permite comparar cuán homogéneos son los precios dentro de cada categoría:

SELECT
    c.nombre AS categoria,
    COUNT(*) AS productos,
    ROUND(AVG(p.precio), 2) AS precio_medio,
    ROUND(VARIANCE(p.precio), 2) AS varianza,
    ROUND(STD(p.precio), 2) AS desviacion
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
ORDER BY varianza DESC;
categoriaproductosprecio_mediovarianzadesviacion
Portátiles81245.50119163.04345.20
Smartphones12785.4297531.29312.30
Deportes4189.9921083.04145.20
Hogar5124.809702.2598.50
Ropa mujer664.991482.2538.50
Ropa hombre659.991075.8432.80
Accesorios electrónicos742.85835.2128.90
Libros222.5056.257.50

Los portátiles tienen la mayor varianza (119163.04), lo que indica la mayor dispersión de precios. Los libros tienen la menor varianza (56.25), con precios muy cercanos entre sí. Cuando comparas categorías con escalas de precios muy diferentes, el coeficiente de variación (desviación entre media) es más apropiado que la varianza en bruto.

Caso práctico: análisis de consistencia en ventas

La varianza de los totales de pedido puede revelar cuán predecibles son las ventas:

SELECT
    DATE_FORMAT(fecha_pedido, '%Y-%m') AS mes,
    COUNT(*) AS num_pedidos,
    ROUND(AVG(total), 2) AS ticket_medio,
    ROUND(VARIANCE(total), 2) AS varianza_ticket,
    ROUND(STD(total), 2) AS desviacion_ticket
FROM pedidos
WHERE estado = 'completado'
    AND YEAR(fecha_pedido) = 2025
GROUP BY DATE_FORMAT(fecha_pedido, '%Y-%m')
ORDER BY mes;
mesnum_pedidosticket_mediovarianza_ticketdesviacion_ticket
2025-0120922.54148379.04385.20
2025-0223927.00170156.25412.50
2025-0327958.90127306.24356.80
2025-0421946.22158722.56398.40
2025-0525966.03143565.21378.90
2025-0630985.35119439.36345.60

Junio tiene el ticket medio más alto y la varianza más baja, lo que indica ventas consistentes con valores similares. Febrero, por el contrario, tiene alta varianza, lo que sugiere una mezcla de pedidos pequeños y grandes.

Caso práctico: descomposición de varianza entre grupos

Un uso avanzado de la varianza es descomponer la variabilidad total en dos componentes: la varianza entre grupos (diferencias entre las medias de cada categoría) y la varianza dentro de los grupos (diferencias dentro de cada categoría):

SELECT
    ROUND(VARIANCE(precio), 2) AS varianza_total,
    ROUND(VARIANCE(avg_cat), 2) AS varianza_entre_grupos,
    ROUND(AVG(var_dentro), 2) AS varianza_dentro_grupos
FROM productos p
JOIN (
    SELECT
        categoria_id,
        AVG(precio) AS avg_cat,
        VARIANCE(precio) AS var_dentro
    FROM productos
    GROUP BY categoria_id
) stats ON p.categoria_id = stats.categoria_id;
varianza_totalvarianza_entre_gruposvarianza_dentro_grupos
183757.41148230.5035526.91

La mayor parte de la varianza total (148230.50 de 183757.41) se debe a las diferencias entre categorías, no a las diferencias dentro de cada categoría. Esto confirma que el precio depende mucho más de la categoría del producto que de otros factores.

Manejo de NULL

VARIANCE ignora los valores NULL. Si todas las filas contienen NULL, devuelve NULL. Si solo hay un valor no nulo, la varianza es 0:

SELECT
    VARIANCE(descuento) AS varianza_descuento,
    COUNT(descuento) AS productos_con_descuento
FROM productos;
varianza_descuentoproductos_con_descuento
42.3512

La varianza de 42.35 se calcula solo sobre los 12 productos que tienen descuento. Los 38 productos con descuento como NULL se excluyen completamente del cálculo.

Si quieres incluir los NULL como cero:

SELECT
    ROUND(VARIANCE(descuento), 2) AS var_sin_null,
    ROUND(VARIANCE(IFNULL(descuento, 0)), 2) AS var_con_ceros
FROM productos;
var_sin_nullvar_con_ceros
42.3518.90

Al incluir los ceros, la varianza cambia porque el promedio baja (hay más valores cerca de cero) y la distribución se modifica.

Combinación con otras funciones

VARIANCE se combina con HAVING para filtrar grupos según su dispersión:

SELECT
    c.nombre AS categoria,
    ROUND(AVG(p.precio), 2) AS precio_medio,
    ROUND(VARIANCE(p.precio), 2) AS varianza
FROM productos p
JOIN categorias c ON p.categoria_id = c.id
GROUP BY c.nombre
HAVING VARIANCE(p.precio) > 10000
ORDER BY varianza DESC;
categoriaprecio_mediovarianza
Portátiles1245.50119163.04
Smartphones785.4297531.29
Deportes189.9921083.04

Esta consulta encuentra las categorías con mayor dispersión de precios, que podrían beneficiarse de una segmentación en subcategorías (como "Smartphones gama alta" y "Smartphones gama media").

También puedes verificar la relación entre VARIANCE y STD:

SELECT
    ROUND(VARIANCE(precio), 4) AS varianza,
    ROUND(STD(precio) * STD(precio), 4) AS std_al_cuadrado,
    ROUND(VARIANCE(precio) - STD(precio) * STD(precio), 10) AS diferencia
FROM productos;

La diferencia será 0 (o prácticamente 0, salvo por errores de redondeo de punto flotante), confirmando que VARIANCE = STD^2.

En el siguiente artículo veremos VAR_SAMP para la varianza muestral.

Escrito por Eduardo Lázaro