CORR(y, x) retorna o coeficiente de correlacao de Pearson entre duas colunas numericas como um unico agregado. O resultado fica sempre entre -1 e 1 e mostra com que forca os dois valores se movem juntos de forma linear.
O que CORR calcula e como ler
A funcao mede uma relacao linear: o quao bem a nuvem de pontos (x, y) se encaixa em uma reta. O valor e interpretado pelo sinal e pela magnitude:
+1 e uma relacao direta perfeita: mais x, mais y.
-1 e uma inversa perfeita: mais x, menos y.
0 significa que nao ha vinculo linear (pode haver um nao linear).
- Um
|r| de cerca de 0.7 ou mais costuma ser chamado de forte, e 0.3-0.7 de moderado.
A ordem dos argumentos nao muda o coeficiente: CORR(a, b) = CORR(b, a). A ordem so passa a importar mais adiante, com as funcoes de regressao.
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';
Correlacao nao e causalidade
A grande armadilha. Um r alto so diz que os numeros se movem juntos, nao que um cause o outro. Fontes classicas de correlacao espuria:
- Um fator comum oculto (sazonalidade ou uma campanha puxam para cima pedidos e trafego ao mesmo tempo).
- Efeitos de escala: clientes grandes fazem mais pedidos e tem um ticket medio maior.
- Puro ruido em uma amostra pequena:
r = 0.9 sobre 5 linhas quase nao significa 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;
Sempre mostre o COUNT(*) ao lado: um coeficiente sem o tamanho da amostra e facil de interpretar errado.
Tratamento de NULL e casos extremos
CORR so usa pares em que ambos os valores nao sao NULL. Se x ou y for NULL, a linha inteira e descartada silenciosamente do calculo. Esse e o comportamento padrao, nao um erro.
- Se houver menos de dois pares validos, o resultado e
NULL.
- Se
x ou y for constante (variancia zero), a divisao por zero produz NULL em vez de lancar uma excecao.
SELECT dept,
COUNT(*) AS rows_total,
COUNT(salary) AS rows_with_salary,
CORR(salary, manager_id) AS r
FROM employees
GROUP BY dept;
Pegadinha: COUNT(*) e o numero de pares que CORR realmente usou podem ser diferentes. Para saber o tamanho honesto da amostra, conte os pares de forma explicita, por exemplo com COUNT(*) FILTER (WHERE salary IS NOT NULL AND manager_id IS NOT NULL).
CORR responde "quao forte e o vinculo" mas nao da a equacao da reta. A familia REGR_* da, e e barato calcula-la na mesma passada:
REGR_SLOPE(y, x) e a inclinacao da reta de tendencia.
REGR_INTERCEPT(y, x) e onde ela cruza o eixo y.
REGR_R2(y, x) e o coeficiente de determinacao, igual a r ao quadrado.
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;
Previsao: predicted_amount = intercept + slope * age_days.
Diferencas entre bancos de dados
- PostgreSQL: suporte completo a
CORR, COVAR_POP, COVAR_SAMP e todo o conjunto REGR_*.
- ClickHouse: tem
corr(x, y) mas nao REGR_*; a inclinacao e derivada na mao a partir de covarPop e varPop.
- MySQL: nao existe
CORR. Voce monta a formula com AVG, STDDEV_POP e o produto medio, ou calcula na aplicacao.
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;
Em resumo: CORR e uma forma barata e de passada unica para estimar a forca de um vinculo linear, e um REGR_* ao lado transforma essa estimativa em uma equacao de tendencia pronta para uso.
CORR(y, x)retorna o coeficiente de correlacao de Pearson entre duas colunas numericas como um unico agregado. O resultado fica sempre entre -1 e 1 e mostra com que forca os dois valores se movem juntos de forma linear.O que CORR calcula e como ler
A funcao mede uma relacao linear: o quao bem a nuvem de pontos
(x, y)se encaixa em uma reta. O valor e interpretado pelo sinal e pela magnitude:+1e uma relacao direta perfeita: maisx, maisy.-1e uma inversa perfeita: maisx, menosy.0significa que nao ha vinculo linear (pode haver um nao linear).|r|de cerca de0.7ou mais costuma ser chamado de forte, e0.3-0.7de moderado.A ordem dos argumentos nao muda o coeficiente:
CORR(a, b) = CORR(b, a). A ordem so passa a importar mais adiante, com as funcoes de regressao.-- 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';Correlacao nao e causalidade
A grande armadilha. Um
ralto so diz que os numeros se movem juntos, nao que um cause o outro. Fontes classicas de correlacao espuria:r = 0.9sobre 5 linhas quase nao significa 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;Sempre mostre o
COUNT(*)ao lado: um coeficiente sem o tamanho da amostra e facil de interpretar errado.Tratamento de NULL e casos extremos
CORRso usa pares em que ambos os valores nao saoNULL. SexouyforNULL, a linha inteira e descartada silenciosamente do calculo. Esse e o comportamento padrao, nao um erro.NULL.xouyfor constante (variancia zero), a divisao por zero produzNULLem vez de lancar uma excecao.-- 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;Pegadinha:
COUNT(*)e o numero de pares queCORRrealmente usou podem ser diferentes. Para saber o tamanho honesto da amostra, conte os pares de forma explicita, por exemplo comCOUNT(*) FILTER (WHERE salary IS NOT NULL AND manager_id IS NOT NULL).Combinando com REGR_* para uma reta de tendencia
CORRresponde "quao forte e o vinculo" mas nao da a equacao da reta. A familiaREGR_*da, e e barato calcula-la na mesma passada:REGR_SLOPE(y, x)e a inclinacao da reta de tendencia.REGR_INTERCEPT(y, x)e onde ela cruza o eixoy.REGR_R2(y, x)e o coeficiente de determinacao, igual arao quadrado.-- 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;Previsao:
predicted_amount = intercept + slope * age_days.Diferencas entre bancos de dados
CORR,COVAR_POP,COVAR_SAMPe todo o conjuntoREGR_*.corr(x, y)mas naoREGR_*; a inclinacao e derivada na mao a partir decovarPopevarPop.CORR. Voce monta a formula comAVG,STDDEV_POPe o produto medio, ou calcula na aplicacao.-- 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;Em resumo:
CORRe uma forma barata e de passada unica para estimar a forca de um vinculo linear, e umREGR_*ao lado transforma essa estimativa em uma equacao de tendencia pronta para uso.