REGR_SLOPE y REGR_INTERCEPT son funciones de agregacion que ajustan una recta por minimos cuadrados dentro de la propia consulta. Juntas dan la ecuacion y = slope * x + intercept, es decir, una linea de tendencia y una formula de prediccion lista, sin exportar los datos a Python o R.
Sintaxis y orden de los argumentos
Ambas funciones reciben dos argumentos, y aqui se esconde la trampa principal. El orden es: primero la variable dependiente y (lo que predices), luego la independiente x (a partir de la cual predices).
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';
Que hace cada parte:
REGR_SLOPE(y, x) -- la pendiente: cuanto cambia y en promedio por cada aumento de una unidad en x.
REGR_INTERCEPT(y, x) -- donde la recta corta el eje y (su valor en x = 0).
REGR_COUNT(y, x) -- el numero de pares donde ambos valores no son NULL. Ese es tu tamano de muestra.
Trampa: el orden es (y, x), no (x, y). Si los inviertes, ajustas la relacion inversa y la prediccion se desvia. Recuerdalo por el significado: "lo que predecimos" va primero.
Tendencia de ingresos por dia
Convierte la marca de tiempo en un numero (segundos de epoch) y pregunta si el pedido medio crece con el tiempo. Una pendiente escalada a dias se lee mejor que una 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';
Un amount_per_day positivo significa que los importes de los pedidos tienden a subir dia tras dia; uno negativo, que bajan. Manten REGR_COUNT al lado: una pendiente sobre tres puntos es ruido, no una tendencia.
Prediccion sin un paquete externo
Como ya tienes slope e intercept, predecir es solo sustituir un x en la ecuacion de la recta. Calcula los coeficientes una vez en un CTE y predice los ingresos en una fecha 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;
El mismo truco no se limita al tiempo. Toma el salario en funcion del tamano del equipo de un jefe -- un ajuste lineal 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;
Calidad del ajuste y trampas
La pendiente por si sola no dice nada sobre que tan bien describe la recta los datos. Para eso tienes REGR_R2 (el coeficiente de determinacion, de 0 a 1) y CORR (correlacion):
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';
Cosas que conviene tener presentes:
- Un
R2 cercano a cero significa que la recta es casi inutil; la prediccion no merece confianza.
- Si todos los
x son identicos (varianza cero), la pendiente queda indefinida y la funcion devuelve NULL en vez de fallar.
- Las filas donde
y o x es NULL se descartan -- por eso siempre cotejas con REGR_COUNT.
- La regresion lineal solo ve una recta. Aplanara la estacionalidad y el crecimiento exponencial y te enganara.
Diferencias entre motores
- MySQL no tiene funciones
REGR_*. Calcula la pendiente a mano: 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 ofrece
simpleLinearRegression(x, y), y aqui el orden de los argumentos es inverso -- x va primero. Devuelve una tupla (slope, intercept).
- BigQuery no tiene
REGR_SLOPE ni REGR_INTERCEPT integradas -- la pendiente y el intercepto se calculan a mano con SUM, AVG y COVAR_POP/VAR_POP, o se entrena un modelo con CREATE MODEL ... OPTIONS(model_type='linear_reg') en BigQuery ML. Snowflake, en cambio, si soporta los estandar REGR_SLOPE(y, x) y REGR_INTERCEPT(y, x), igual que PostgreSQL.
Cuando quieres una linea de tendencia rapida o una prediccion barata dentro de la base de datos, REGR_SLOPE y REGR_INTERCEPT te ahorran todo un viaje a una herramienta analitica externa -- solo manten el orden de los argumentos claro y revisa el tamano de la muestra.
REGR_SLOPEyREGR_INTERCEPTson funciones de agregacion que ajustan una recta por minimos cuadrados dentro de la propia consulta. Juntas dan la ecuaciony = slope * x + intercept, es decir, una linea de tendencia y una formula de prediccion lista, sin exportar los datos a Python o R.Sintaxis y orden de los argumentos
Ambas funciones reciben dos argumentos, y aqui se esconde la trampa principal. El orden es: primero la variable dependiente
y(lo que predices), luego la independientex(a partir de la cual predices).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';Que hace cada parte:
REGR_SLOPE(y, x)-- la pendiente: cuanto cambiayen promedio por cada aumento de una unidad enx.REGR_INTERCEPT(y, x)-- donde la recta corta el ejey(su valor enx = 0).REGR_COUNT(y, x)-- el numero de pares donde ambos valores no sonNULL. Ese es tu tamano de muestra.Tendencia de ingresos por dia
Convierte la marca de tiempo en un numero (segundos de epoch) y pregunta si el pedido medio crece con el tiempo. Una pendiente escalada a dias se lee mejor que una 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';Un
amount_per_daypositivo significa que los importes de los pedidos tienden a subir dia tras dia; uno negativo, que bajan. MantenREGR_COUNTal lado: una pendiente sobre tres puntos es ruido, no una tendencia.Prediccion sin un paquete externo
Como ya tienes
slopeeintercept, predecir es solo sustituir unxen la ecuacion de la recta. Calcula los coeficientes una vez en un CTE y predice los ingresos en una fecha 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;El mismo truco no se limita al tiempo. Toma el salario en funcion del tamano del equipo de un jefe -- un ajuste lineal 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;Calidad del ajuste y trampas
La pendiente por si sola no dice nada sobre que tan bien describe la recta los datos. Para eso tienes
REGR_R2(el coeficiente de determinacion, de 0 a 1) yCORR(correlacion):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';Cosas que conviene tener presentes:
R2cercano a cero significa que la recta es casi inutil; la prediccion no merece confianza.xson identicos (varianza cero), la pendiente queda indefinida y la funcion devuelveNULLen vez de fallar.yoxesNULLse descartan -- por eso siempre cotejas conREGR_COUNT.Diferencias entre motores
REGR_*. Calcula la pendiente a mano:slope = (n*SUM(x*y) - SUM(x)*SUM(y)) / (n*SUM(x*x) - SUM(x)*SUM(x)), eintercept = (SUM(y) - slope*SUM(x)) / n.simpleLinearRegression(x, y), y aqui el orden de los argumentos es inverso --xva primero. Devuelve una tupla(slope, intercept).REGR_SLOPEniREGR_INTERCEPTintegradas -- la pendiente y el intercepto se calculan a mano conSUM,AVGyCOVAR_POP/VAR_POP, o se entrena un modelo conCREATE MODEL ... OPTIONS(model_type='linear_reg')en BigQuery ML. Snowflake, en cambio, si soporta los estandarREGR_SLOPE(y, x)yREGR_INTERCEPT(y, x), igual que PostgreSQL.Cuando quieres una linea de tendencia rapida o una prediccion barata dentro de la base de datos,
REGR_SLOPEyREGR_INTERCEPTte ahorran todo un viaje a una herramienta analitica externa -- solo manten el orden de los argumentos claro y revisa el tamano de la muestra.