sqlpostgresqlvariancestatistics

VARIANCE en SQL: VAR_SAMP frente a VAR_POP y su relacion con STDDEV

Como funcionan VAR_SAMP y VAR_POP en PostgreSQL, por que VARIANCE equivale a VAR_SAMP y como la varianza se relaciona con la desviacion estandar.

3 min de lecturaReferencesql · postgresql · variance · statistics · aggregate

La varianza mide cuanto se dispersan los valores alrededor de su media: cuanto mayor es, mas "ancha" es la distribucion de los datos. Es la media de las desviaciones al cuadrado respecto a la media, expresada en las unidades de entrada al cuadrado. SQL ofrece dos variantes, la muestral VAR_SAMP y la poblacional VAR_POP, y la diferencia importa mas de lo que parece.

Dos funciones y un atajo

PostgreSQL expone tres nombres, pero detras solo hay dos formulas:

  • VAR_POP(x) es la varianza poblacional: divide la suma de desviaciones al cuadrado entre N.
  • VAR_SAMP(x) es la varianza muestral: divide entre N - 1 (correccion de Bessel).
  • VARIANCE(x) es simplemente un alias de VAR_SAMP.
SELECT
  var_samp(amount) AS sample_variance,
  var_pop(amount)  AS pop_variance,
  variance(amount) AS bare_variance   -- equals var_samp
FROM orders;

Conclusion clave: en PostgreSQL, el VARIANCE a secas NO es una opcion "neutral", divide entre N - 1. En ClickHouse las funciones explicitas se llaman varSamp y varPop. MySQL es la trampa: alli VARIANCE es un sinonimo de VAR_POP (division entre N), no de VAR_SAMP. Por eso una consulta con VARIANCE a secas devuelve numeros distintos en PostgreSQL y en MySQL para los mismos datos. Para codigo portable, escribe siempre de forma explicita la version que necesitas.

Muestra o poblacion

Cual necesitas depende de lo que representen tus filas.

  • Si las filas son TODOS los objetos que te interesan (por ejemplo, todos los pedidos de un dia concreto), usa VAR_POP.
  • Si las filas son una muestra de un conjunto mayor no observado (pedidos como muestra del comportamiento general de los clientes), usa VAR_SAMP.
-- Spread of order amounts per status, treating each group as a sample
SELECT
  status,
  count(*)              AS n,
  round(var_samp(amount)::numeric, 2) AS variance
FROM orders
GROUP BY status
ORDER BY variance DESC NULLS LAST;

Con N grande, la diferencia entre dividir entre N y entre N - 1 desaparece. En grupos pequenos se nota: con N = 2, la varianza muestral es exactamente el doble de la poblacional. Por eso, en segmentos dispersos o con muchos grupos pequenos, la eleccion de la funcion mueve directamente los numeros del informe y conviene hacerla explicita en lugar de confiar en un valor por defecto. Cuando dudes si tus filas son una poblacion completa o una muestra, tratarlas como muestra y usar VAR_SAMP suele ser lo mas seguro: da una estimacion no sesgada de la dispersion, mientras que VAR_POP sobre una muestra la subestima de forma sistematica.

La varianza es la desviacion estandar al cuadrado

Varianza y desviacion estandar son dos caras del mismo numero: STDDEV es la raiz cuadrada de VARIANCE. STDDEV_SAMP se corresponde con VAR_SAMP y STDDEV_POP con VAR_POP. Esa identidad es util para comprobaciones y para cambiar de unidades.

SELECT
  var_samp(salary)             AS variance_salary,
  stddev_samp(salary)          AS stddev_salary,
  sqrt(var_samp(salary))       AS stddev_via_sqrt  -- matches stddev_samp
FROM employees;

La desviacion estandar esta en las mismas unidades que los datos (dolares, euros), mientras que la varianza esta en esas unidades al cuadrado. Por eso los informes casi siempre muestran STDDEV a las personas y reservan la varianza para los calculos internos, donde el cuadrado resulta comodo (por ejemplo, al sumar las varianzas de variables independientes).

Detalles numericos y trampas

  • Los NULL se ignoran en silencio: VAR_SAMP solo cuenta los valores no nulos, y N es ese recuento, no el total de filas.
  • En una sola fila, VAR_SAMP devuelve NULL (no puedes dividir entre N - 1 = 0), mientras que VAR_POP devuelve 0. Esta es la trampa clasica al agrupar: los grupos de una sola fila producen NULL de repente.
-- Single-row group: var_samp is NULL, var_pop is 0
SELECT
  dept,
  count(*)        AS n,
  var_samp(salary) AS vs,   -- NULL when n = 1
  var_pop(salary)  AS vp    -- 0 when n = 1
FROM employees
GROUP BY dept;
  • El tipo de resultado es double precision para entradas float y numeric para entradas enteras y numeric. Con numeros muy grandes la ruta float puede perder precision; convierte a numeric cuando necesites estabilidad.
  • No calcules la varianza sobre promedios ya agregados, da un resultado erroneo. La varianza se toma sobre los valores originales sin agregar.
-- Cast to numeric for stable variance on large monetary values
SELECT var_samp(amount::numeric) AS stable_variance
FROM orders
WHERE status = 'paid';

Regla corta: en PostgreSQL usa VAR_SAMP (o VARIANCE) para muestras, VAR_POP para una poblacion completa, vigila los NULL en grupos de una sola fila y pasa a STDDEV mediante la raiz cuadrada cuando quieras unidades legibles. Y recuerda que en MySQL VARIANCE significa VAR_POP.

Practica con ejercicios reales

Resuelve ejercicios en el entrenador de SQL con corrección instantánea y pistas.

Abrir el entrenador