CORR(y, x) devuelve el coeficiente de correlacion de Pearson entre dos columnas numericas como un unico agregado. El resultado siempre cae entre -1 y 1 e indica con que fuerza ambos valores se mueven juntos de forma lineal.
Que calcula CORR y como leerlo
La funcion mide una relacion lineal: como de bien se ajusta la nube de puntos (x, y) a una recta. El valor se interpreta por su signo y su magnitud:
+1 es una relacion directa perfecta: mas x, mas y.
-1 es una inversa perfecta: mas x, menos y.
0 significa que no hay vinculo lineal (puede existir uno no lineal).
- Un
|r| de unos 0.7 o mas suele llamarse fuerte, y 0.3-0.7 moderado.
El orden de los argumentos no cambia el coeficiente: CORR(a, b) = CORR(b, a). El orden empezara a importar mas adelante, con las funciones de regresion.
SELECT CORR(
o.amount,
EXTRACT(EPOCH FROM (o.created_at - u.created_at)) / 86400
) AS amount_vs_age
FROM orders o
JOIN users u ON u.id = o.user_id
WHERE o.status = 'paid';
Correlacion no es causalidad
La gran trampa. Un r alto solo dice que los numeros se mueven juntos, no que uno cause el otro. Fuentes clasicas de correlacion espuria:
- Un factor comun oculto (la estacionalidad o una campana empujan a la vez pedidos y trafico).
- Efectos de escala: los clientes grandes hacen mas pedidos y tienen un ticket medio mayor.
- Puro ruido en una muestra pequena:
r = 0.9 sobre 5 filas no significa casi nada.
SELECT u.country,
COUNT(*) AS n,
CORR(o.amount, u.id) AS r
FROM orders o
JOIN users u ON u.id = o.user_id
GROUP BY u.country
HAVING COUNT(*) >= 30
ORDER BY r DESC;
Muestra siempre el COUNT(*) al lado: un coeficiente sin tamano de muestra es facil de malinterpretar.
Tratamiento de NULL y casos limite
CORR solo usa pares en los que ambos valores no son NULL. Si x o y es NULL, toda la fila se descarta en silencio del calculo. Es el comportamiento por defecto, no un error.
- Si hay menos de dos pares validos, el resultado es
NULL.
- Si
x o y es constante (varianza cero), la division por cero da NULL en lugar de lanzar una excepcion.
SELECT dept,
COUNT(*) AS rows_total,
COUNT(salary) AS rows_with_salary,
CORR(salary, manager_id) AS r
FROM employees
GROUP BY dept;
Gotcha: COUNT(*) y el numero de pares que CORR usa de verdad pueden diferir. Para conocer el tamano real de muestra, cuenta los pares de forma explicita, por ejemplo con COUNT(*) FILTER (WHERE salary IS NOT NULL AND manager_id IS NOT NULL).
Combinacion con REGR_* para una recta de tendencia
CORR responde a "que tan fuerte es el vinculo" pero no da la ecuacion de la recta. La familia REGR_* si lo hace, y es barato calcularla en la misma pasada:
REGR_SLOPE(y, x) es la pendiente de la recta de tendencia.
REGR_INTERCEPT(y, x) es donde cruza el eje y.
REGR_R2(y, x) es el coeficiente de determinacion, igual a r al cuadrado.
SELECT REGR_SLOPE(o.amount, age_days) AS slope,
REGR_INTERCEPT(o.amount, age_days) AS intercept,
CORR(o.amount, age_days) AS r,
REGR_R2(o.amount, age_days) AS r_squared
FROM (
SELECT o.amount,
EXTRACT(EPOCH FROM (o.created_at - u.created_at)) / 86400 AS age_days
FROM orders o
JOIN users u ON u.id = o.user_id
) o;
Pronostico: predicted_amount = intercept + slope * age_days.
Diferencias entre bases de datos
- PostgreSQL: soporte completo de
CORR, COVAR_POP, COVAR_SAMP y todo el conjunto REGR_*.
- ClickHouse: tiene
corr(x, y) pero no REGR_*; la pendiente se deriva a mano desde covarPop y varPop.
- MySQL: no existe
CORR. Se arma la formula con AVG, STDDEV_POP y el producto medio, o se calcula en la aplicacion.
SELECT (AVG(x * y) - AVG(x) * AVG(y))
/ (STDDEV_POP(x) * STDDEV_POP(y)) AS r
FROM (SELECT amount AS x, user_id AS y FROM orders) t;
En resumen: CORR es una forma barata y de una sola pasada de estimar la fuerza de un vinculo lineal, y un REGR_* al lado convierte esa estimacion en una ecuacion de tendencia lista para usar.
CORR(y, x)devuelve el coeficiente de correlacion de Pearson entre dos columnas numericas como un unico agregado. El resultado siempre cae entre -1 y 1 e indica con que fuerza ambos valores se mueven juntos de forma lineal.Que calcula CORR y como leerlo
La funcion mide una relacion lineal: como de bien se ajusta la nube de puntos
(x, y)a una recta. El valor se interpreta por su signo y su magnitud:+1es una relacion directa perfecta: masx, masy.-1es una inversa perfecta: masx, menosy.0significa que no hay vinculo lineal (puede existir uno no lineal).|r|de unos0.7o mas suele llamarse fuerte, y0.3-0.7moderado.El orden de los argumentos no cambia el coeficiente:
CORR(a, b) = CORR(b, a). El orden empezara a importar mas adelante, con las funciones de regresion.-- Correlation between order amount and the user's account age in days SELECT CORR( o.amount, EXTRACT(EPOCH FROM (o.created_at - u.created_at)) / 86400 ) AS amount_vs_age FROM orders o JOIN users u ON u.id = o.user_id WHERE o.status = 'paid';Correlacion no es causalidad
La gran trampa. Un
ralto solo dice que los numeros se mueven juntos, no que uno cause el otro. Fuentes clasicas de correlacion espuria:r = 0.9sobre 5 filas no significa casi nada.-- Per-country correlation, but only where the sample is large enough to trust SELECT u.country, COUNT(*) AS n, CORR(o.amount, u.id) AS r FROM orders o JOIN users u ON u.id = o.user_id GROUP BY u.country HAVING COUNT(*) >= 30 ORDER BY r DESC;Muestra siempre el
COUNT(*)al lado: un coeficiente sin tamano de muestra es facil de malinterpretar.Tratamiento de NULL y casos limite
CORRsolo usa pares en los que ambos valores no sonNULL. SixoyesNULL, toda la fila se descarta en silencio del calculo. Es el comportamiento por defecto, no un error.NULL.xoyes constante (varianza cero), la division por cero daNULLen lugar de lanzar una excepcion.-- Salary vs manager presence: rows with NULL manager_id are dropped automatically SELECT dept, COUNT(*) AS rows_total, COUNT(salary) AS rows_with_salary, CORR(salary, manager_id) AS r FROM employees GROUP BY dept;Gotcha:
COUNT(*)y el numero de pares queCORRusa de verdad pueden diferir. Para conocer el tamano real de muestra, cuenta los pares de forma explicita, por ejemplo conCOUNT(*) FILTER (WHERE salary IS NOT NULL AND manager_id IS NOT NULL).Combinacion con REGR_* para una recta de tendencia
CORRresponde a "que tan fuerte es el vinculo" pero no da la ecuacion de la recta. La familiaREGR_*si lo hace, y es barato calcularla en la misma pasada:REGR_SLOPE(y, x)es la pendiente de la recta de tendencia.REGR_INTERCEPT(y, x)es donde cruza el ejey.REGR_R2(y, x)es el coeficiente de determinacion, igual aral cuadrado.-- Trend line for amount as a function of account age, plus strength of fit SELECT REGR_SLOPE(o.amount, age_days) AS slope, REGR_INTERCEPT(o.amount, age_days) AS intercept, CORR(o.amount, age_days) AS r, REGR_R2(o.amount, age_days) AS r_squared FROM ( SELECT o.amount, EXTRACT(EPOCH FROM (o.created_at - u.created_at)) / 86400 AS age_days FROM orders o JOIN users u ON u.id = o.user_id ) o;Pronostico:
predicted_amount = intercept + slope * age_days.Diferencias entre bases de datos
CORR,COVAR_POP,COVAR_SAMPy todo el conjuntoREGR_*.corr(x, y)pero noREGR_*; la pendiente se deriva a mano desdecovarPopyvarPop.CORR. Se arma la formula conAVG,STDDEV_POPy el producto medio, o se calcula en la aplicacion.-- Portable fallback that works even without a built-in CORR SELECT (AVG(x * y) - AVG(x) * AVG(y)) / (STDDEV_POP(x) * STDDEV_POP(y)) AS r FROM (SELECT amount AS x, user_id AS y FROM orders) t;En resumen:
CORRes una forma barata y de una sola pasada de estimar la fuerza de un vinculo lineal, y unREGR_*al lado convierte esa estimacion en una ecuacion de tendencia lista para usar.