sqlpostgresqlstatisticsaggregation

REGR_SLOPE e REGR_INTERCEPT no PostgreSQL: linha de tendencia e previsao em uma consulta

Construa uma linha de minimos quadrados no SQL com REGR_SLOPE e REGR_INTERCEPT, cuide da ordem (y, x), confira REGR_COUNT e faca previsoes sem um pacote estatistico externo.

3 min de leituraReferencesql · postgresql · statistics · aggregation · analytics · forecasting

REGR_SLOPE e REGR_INTERCEPT sao funcoes de agregacao que ajustam uma reta por minimos quadrados dentro da propria consulta. Juntas elas entregam a equacao y = slope * x + intercept, ou seja, uma linha de tendencia e uma formula de previsao pronta, sem precisar exportar os dados para Python ou R.

Sintaxe e ordem dos argumentos

Ambas as funcoes recebem dois argumentos, e e aqui que mora a principal armadilha. A ordem e: primeiro a variavel dependente y (o que voce preve), depois a independente x (a partir da qual voce preve).

SELECT
    REGR_SLOPE(amount, extract(epoch from created_at)) AS slope,
    REGR_INTERCEPT(amount, extract(epoch from created_at)) AS intercept,
    REGR_COUNT(amount, extract(epoch from created_at)) AS n
FROM orders
WHERE status = 'paid';

O que cada parte faz:

  • REGR_SLOPE(y, x) -- a inclinacao: quanto y muda em media a cada aumento de uma unidade em x.
  • REGR_INTERCEPT(y, x) -- onde a reta cruza o eixo y (seu valor em x = 0).
  • REGR_COUNT(y, x) -- o numero de pares onde ambos os valores nao sao NULL. Esse e o seu tamanho de amostra.

Pegadinha: a ordem e (y, x), nao (x, y). Se inverter, voce ajusta a relacao inversa e a previsao desanda. Lembre pelo significado: "o que prevemos" vem primeiro.

Tendencia de receita por dia

Converta o timestamp em um numero (segundos de epoch) e pergunte se o pedido medio cresce com o tempo. Uma inclinacao escalada para dias le-se melhor do que uma por segundo:

SELECT
    REGR_SLOPE(amount, extract(epoch from created_at)) * 86400 AS amount_per_day,
    REGR_COUNT(amount, extract(epoch from created_at)) AS sample_size
FROM orders
WHERE status = 'paid';

Um amount_per_day positivo significa que os valores dos pedidos tendem a subir dia apos dia; um negativo, que encolhem. Mantenha o REGR_COUNT ao lado: uma inclinacao sobre tres pontos e ruido, nao uma tendencia.

Previsao sem um pacote externo

Como voce ja tem slope e intercept, prever e apenas substituir um x na equacao da reta. Calcule os coeficientes uma vez em um CTE e preveja a receita em uma data futura:

WITH model AS (
    SELECT
        REGR_SLOPE(amount, extract(epoch from created_at)) AS slope,
        REGR_INTERCEPT(amount, extract(epoch from created_at)) AS intercept
    FROM orders
    WHERE status = 'paid'
)
SELECT
    slope * extract(epoch from TIMESTAMP '2026-12-31') + intercept AS forecast_amount
FROM model;

O mesmo truque nao se limita ao tempo. Pegue o salario em funcao do tamanho da equipe de um gerente -- um ajuste linear por departamento:

SELECT
    dept,
    REGR_SLOPE(salary, reports) AS salary_per_report,
    REGR_INTERCEPT(salary, reports) AS base_salary
FROM (
    SELECT
        e.dept,
        e.salary,
        count(r.id) AS reports
    FROM employees e
    LEFT JOIN employees r ON r.manager_id = e.id
    GROUP BY e.id, e.dept, e.salary
) s
GROUP BY dept;

Qualidade do ajuste e armadilhas

A inclinacao sozinha nao diz nada sobre o quao bem a reta descreve os dados. Para isso voce tem REGR_R2 (o coeficiente de determinacao, de 0 a 1) e CORR (correlacao):

SELECT
    REGR_R2(amount, extract(epoch from created_at)) AS r_squared,
    CORR(amount, extract(epoch from created_at)) AS correlation
FROM orders
WHERE status = 'paid';

Coisas a ter em mente:

  • Um R2 proximo de zero significa que a reta e quase inutil; a previsao nao merece confianca.
  • Se todos os x forem identicos (variancia zero), a inclinacao fica indefinida e a funcao retorna NULL em vez de dar erro.
  • Linhas onde y ou x e NULL sao descartadas -- por isso voce sempre confere com o REGR_COUNT.
  • A regressao linear so enxerga uma reta. Ela vai achatar a sazonalidade e o crescimento exponencial e vai te enganar.

Diferencas entre os bancos

  • MySQL nao tem funcoes REGR_*. Calcule a inclinacao na mao: slope = (n*SUM(x*y) - SUM(x)*SUM(y)) / (n*SUM(x*x) - SUM(x)*SUM(x)), e intercept = (SUM(y) - slope*SUM(x)) / n.
  • ClickHouse oferece simpleLinearRegression(x, y), e aqui a ordem dos argumentos e invertida -- x vem primeiro. Ela retorna uma tupla (slope, intercept).
  • BigQuery nao tem REGR_SLOPE nem REGR_INTERCEPT embutidas -- a inclinacao e o intercepto sao calculados na mao com SUM, AVG e COVAR_POP/VAR_POP, ou treina-se um modelo com CREATE MODEL ... OPTIONS(model_type='linear_reg') no BigQuery ML. Snowflake, por outro lado, suporta os padroes REGR_SLOPE(y, x) e REGR_INTERCEPT(y, x), assim como o PostgreSQL.

Quando voce quer uma linha de tendencia rapida ou uma previsao barata dentro do banco, REGR_SLOPE e REGR_INTERCEPT poupam toda uma ida e volta a uma ferramenta analitica externa -- so mantenha a ordem dos argumentos clara e confira o tamanho da amostra.

Pratique com exercícios reais

Resolva exercícios no treinador de SQL com correção instantânea e dicas.

Abrir o treinador