Иногда в базе хочется не просто посчитать сумму, среднее или максимум, а понять направление: растёт показатель или падает. Например:
- увеличивается ли средний чек со временем;
- влияет ли количество подчинённых на зарплату менеджера;
- становится ли доставка дороже при увеличении расстояния;
- меняется ли выручка от недели к неделе.
Для таких задач в PostgreSQL есть агрегатные функции REGR_SLOPE и REGR_INTERCEPT. Они строят простую линейную регрессию прямо внутри SQL-запроса.
Говоря проще, PostgreSQL берёт точки на графике и подбирает к ним прямую линию:
y = slope * x + intercept
Где:
y — показатель, который мы хотим объяснить или предсказать;
x — число, от которого этот показатель зависит;
slope — наклон линии;
intercept — точка пересечения с осью y.
Например, если x — это время, а y — сумма заказа, то такая линия показывает общий тренд: суммы заказов со временем растут, падают или стоят примерно на месте.
Главная польза в том, что всё считается прямо в базе. Не нужно выгружать данные в Excel, Python или BI-систему, если нужен быстрый тренд или грубый прогноз.
Что делают REGR_SLOPE и REGR_INTERCEPT
Функция REGR_SLOPE(y, x) возвращает наклон прямой.
Наклон отвечает на вопрос:
На сколько в среднем меняется y, когда x увеличивается на единицу?
Функция REGR_INTERCEPT(y, x) возвращает свободный коэффициент, то есть значение линии при x = 0.
Вместе они дают готовую формулу:
y = REGR_SLOPE(y, x) * x + REGR_INTERCEPT(y, x)
Допустим, у нас есть заказы. Мы хотим понять, как сумма оплаченного заказа меняется со временем.
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';
Здесь:
amount — это y, сумма заказа;
extract(epoch from created_at) — это x, дата заказа, превращённая в число;
REGR_COUNT показывает, сколько пар значений реально попало в расчёт.
Дата сама по себе не подходит для регрессии, потому что функции нужны числовые оси. Поэтому мы превращаем дату в количество секунд с начала Unix-эпохи.
Главное правило: сначала y, потом x
Самая частая ошибка с REGR_SLOPE и REGR_INTERCEPT — перепутать порядок аргументов.
В обычной речи мы часто говорим «икс и игрек». Из школы тоже помним: сначала x, потом y.
Но в PostgreSQL порядок другой:
REGR_SLOPE(y, x)
REGR_INTERCEPT(y, x)
Сначала идёт зависимая переменная — то, что мы изучаем или предсказываем.
Потом идёт независимая переменная — то, от чего зависит показатель.
Например:
REGR_SLOPE(amount, extract(epoch from created_at))
Читается так:
Как меняется amount при изменении created_at.
А вот так писать не надо:
REGR_SLOPE(extract(epoch from created_at), amount)
Такой запрос не упадёт с ошибкой. Он просто посчитает другую зависимость: как время зависит от суммы заказа. Для нашей задачи это бессмыслица, но PostgreSQL не знает вашего бизнес-смысла и честно вернёт число.
Поэтому держите в голове простую фразу:
Сначала то, что предсказываем. Потом то, по чему предсказываем.
Пример: тренд суммы заказа по дням
Посмотрим, растёт ли сумма оплаченных заказов со временем.
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';
Почему мы умножаем на 86400?
Потому что extract(epoch from created_at) возвращает время в секундах. Значит, сам REGR_SLOPE покажет изменение суммы за одну секунду. Это почти невозможно нормально прочитать.
В сутках 86400 секунд, поэтому после умножения мы получаем более понятный показатель:
На сколько в среднем меняется сумма заказа за день.
Если amount_per_day положительный, суммы заказов в среднем растут.
Если отрицательный — снижаются.
Если близок к нулю — выраженного линейного тренда почти нет.
Но обязательно смотрите на sample_size. Если линия построена по трём заказам, это ещё не тренд. Это просто три точки, которые могли случайно лечь как угодно.
Пример: прогноз на будущую дату
Раз у нас есть slope и intercept, можно подставить будущий x в формулу прямой.
Сначала посчитаем коэффициенты в CTE, а потом сделаем прогноз на конкретную дату.
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;
Здесь происходит ровно то же самое, что в школьной формуле прямой:
y = slope * x + intercept
Только x — это будущая дата, превращённая в число.
Важно понимать: это не магический искусственный интеллект и не полноценная модель продаж. Это простая прямая линия. Она полезна для быстрой оценки направления, но не знает про сезонность, акции, праздники, кризисы, отпускной сезон и внезапный вирусный пост в соцсетях.
Пример: зависимость зарплаты от количества подчинённых
Ось x не обязана быть временем. Это может быть любое числовое значение.
Допустим, мы хотим оценить, как зарплата сотрудника связана с количеством людей, которые ему подчиняются.
Сначала посчитаем для каждого сотрудника количество подчинённых, а потом построим регрессию отдельно по отделам.
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;
Что здесь означает результат:
salary_per_report — насколько в среднем меняется зарплата при увеличении числа подчинённых на одного человека;
base_salary — значение линии при нуле подчинённых;
dept — отдел, внутри которого мы строим зависимость.
Например, если в одном отделе salary_per_report заметно выше, чем в другом, это может означать, что управленческая нагрузка там сильнее связана с зарплатой. Но это не доказывает причинно-следственную связь. Регрессия показывает зависимость в данных, а не объясняет, почему именно она появилась.
Как проверить, можно ли доверять линии
REGR_SLOPE всегда пытается провести прямую, если для этого хватает данных. Но сама по себе прямая ещё не означает, что зависимость хорошая.
Представьте облако точек, разбросанных как попало. Через них всё равно можно провести линию. Вопрос в другом: описывает ли эта линия данные хоть сколько-нибудь нормально?
Для проверки в PostgreSQL есть REGR_R2 и CORR.
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';
REGR_R2 показывает, насколько хорошо линейная модель объясняет разброс данных. Значение находится в диапазоне от 0 до 1.
Примерная бытовая интерпретация такая:
- значение около
0 — линия почти ничего не объясняет;
- значение ближе к
1 — точки лучше ложатся на прямую;
- значение где-то посередине — зависимость есть, но относиться к ней нужно осторожно.
CORR показывает корреляцию между двумя числовыми значениями. Она может быть от -1 до 1.
- ближе к
1 — сильная положительная связь;
- ближе к
-1 — сильная отрицательная связь;
- около
0 — линейной связи почти нет.
Например, если REGR_SLOPE показывает рост, но REGR_R2 почти равен нулю, радоваться рано. Формально наклон есть, но линия плохо описывает данные.
Что происходит с NULL
Регрессионные функции работают только с парами значений, где оба аргумента не равны NULL.
Например, такая строка попадёт в расчёт:
amount = 5000
x = 1770000000
А такие строки будут пропущены:
amount = NULL
x = 1770000000
amount = 5000
x = NULL
Именно поэтому рядом с регрессией полезно выводить REGR_COUNT.
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 sample_size
FROM orders
WHERE status = 'paid';
COUNT(*) покажет все строки после фильтра.
А REGR_COUNT(y, x) покажет только те строки, где одновременно есть и y, и x.
Для аналитики это важная разница. Можно думать, что вы строите тренд по десяти тысячам заказов, а на самом деле в расчёт попали только двести строк, потому что в остальных не было суммы или даты.
Когда REGR_SLOPE вернёт NULL
Иногда результатом будет NULL, и это нормально.
Например, если все значения x одинаковые, наклон посчитать невозможно.
Представьте таблицу, где у всех заказов одна и та же дата. Тогда по оси x нет движения. Нельзя сказать, как меняется y при изменении x, потому что x вообще не меняется.
В такой ситуации REGR_SLOPE вернёт NULL.
То же самое возможно, если после исключения NULL осталось слишком мало пригодных пар данных.
Поэтому в практических запросах хорошо смотреть сразу несколько показателей:
SELECT
REGR_COUNT(amount, extract(epoch from created_at)) AS sample_size,
REGR_SLOPE(amount, extract(epoch from created_at)) AS slope,
REGR_INTERCEPT(amount, extract(epoch from created_at)) AS intercept,
REGR_R2(amount, extract(epoch from created_at)) AS r_squared
FROM orders
WHERE status = 'paid';
Так вы видите не только саму линию, но и то, насколько вообще прилично её было строить.
Линейная регрессия видит только прямую
У REGR_SLOPE и REGR_INTERCEPT есть важное ограничение: они подбирают прямую линию.
А жизнь часто устроена сложнее.
Например:
- продажи могут расти по выходным и падать в будни;
- в декабре может быть сильный сезонный всплеск;
- новый продукт может сначала расти быстро, а потом выйти на плато;
- после рекламной кампании может быть резкий скачок, который испортит общий тренд;
- старые данные могут уже не описывать текущую ситуацию.
Линейная регрессия всё это не понимает. Она берёт облако точек и проводит через него одну прямую.
Поэтому такие функции хороши для первого взгляда на данные:
Есть ли общий рост? Есть ли общее падение? Насколько примерно меняется показатель?
Но для серьёзного прогноза обычно нужны дополнительные проверки, сегментация, сезонность и понимание бизнеса.
Чем REGR_SLOPE отличается от обычных агрегатов
Обычные агрегаты отвечают на простые вопросы:
SELECT
count(*) AS orders_count,
sum(amount) AS total_amount,
avg(amount) AS avg_amount
FROM orders
WHERE status = 'paid';
Такой запрос говорит:
- сколько было заказов;
- какая общая сумма;
- какой средний чек.
Но он не говорит, куда движется показатель.
А регрессионные функции отвечают уже на другой вопрос:
SELECT
REGR_SLOPE(amount, extract(epoch from created_at)) * 86400 AS amount_per_day
FROM orders
WHERE status = 'paid';
Этот запрос спрашивает:
Как сумма заказа меняется во времени?
То есть SUM, AVG и COUNT описывают состояние.
А REGR_SLOPE помогает увидеть направление.
Как это выглядит в аналитической задаче
Допустим, аналитик смотрит на оплаченные заказы и хочет быстро понять, есть ли рост среднего размера заказа.
Можно собрать компактный отчёт:
SELECT
REGR_COUNT(amount, extract(epoch from created_at)) AS sample_size,
avg(amount) AS avg_amount,
REGR_SLOPE(amount, extract(epoch from created_at)) * 86400 AS amount_per_day,
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';
Такой запрос даёт сразу несколько уровней понимания:
sample_size — сколько точек участвовало в расчёте;
avg_amount — средний размер оплаченного заказа;
amount_per_day — примерное изменение суммы заказа за день;
r_squared — насколько хорошо прямая описывает данные;
correlation — насколько сильна линейная связь.
Это уже похоже не на голое число, а на маленький аналитический вывод прямо из SQL.
Отличия в других СУБД
В PostgreSQL порядок аргументов такой:
REGR_SLOPE(y, x)
REGR_INTERCEPT(y, x)
То есть сначала показатель, потом объясняющая переменная.
В других СУБД ситуация может отличаться.
В MySQL функций семейства REGR_* нет. Наклон и свободный коэффициент обычно считают вручную через SUM, AVG и формулы линейной регрессии.
Формула наклона выглядит так:
slope = (n * sum(x * y) - sum(x) * sum(y)) / (n * sum(x * x) - sum(x) * sum(x))
А свободный коэффициент так:
intercept = (sum(y) - slope * sum(x)) / n
В ClickHouse есть функция simpleLinearRegression(x, y). У неё порядок аргументов обратный по сравнению с PostgreSQL: сначала x, потом y. Функция возвращает пару значений: наклон и свободный коэффициент.
В BigQuery встроенных REGR_SLOPE и REGR_INTERCEPT нет. Там коэффициенты можно посчитать вручную через агрегаты вроде SUM, AVG, COVAR_POP и VAR_POP, либо использовать BigQuery ML и обучать модель через CREATE MODEL.
В Snowflake функции REGR_SLOPE(y, x) и REGR_INTERCEPT(y, x) поддерживаются в привычном для PostgreSQL порядке.
Главный вывод простой: при переходе между СУБД всегда проверяйте порядок аргументов. Ошибка не обязательно сломает запрос, но может полностью испортить смысл результата.
Главное из статьи
REGR_SLOPE и REGR_INTERCEPT в PostgreSQL позволяют построить простую линию тренда прямо в SQL.
Они возвращают коэффициенты для формулы:
y = slope * x + intercept
Главное правило — не перепутать аргументы:
REGR_SLOPE(y, x)
REGR_INTERCEPT(y, x)
Сначала идёт то, что мы предсказываем или изучаем. Потом — то, от чего это зависит.
Для дат и времени ось x нужно превращать в число, например через extract(epoch from created_at).
Рядом с регрессией почти всегда полезно выводить REGR_COUNT, потому что строки с NULL в y или x не участвуют в расчёте.
Чтобы понять, насколько линии можно доверять, смотрите на REGR_R2 и CORR.
И самое важное: линейная регрессия — это быстрый способ увидеть общее направление, а не универсальная машина предсказаний. Она отлично подходит для первого анализа, но требует здравого смысла, проверки качества и понимания данных.
Иногда в базе хочется не просто посчитать сумму, среднее или максимум, а понять направление: растёт показатель или падает. Например:
Для таких задач в PostgreSQL есть агрегатные функции
REGR_SLOPEиREGR_INTERCEPT. Они строят простую линейную регрессию прямо внутри SQL-запроса.Говоря проще, PostgreSQL берёт точки на графике и подбирает к ним прямую линию:
Где:
y— показатель, который мы хотим объяснить или предсказать;x— число, от которого этот показатель зависит;slope— наклон линии;intercept— точка пересечения с осьюy.Например, если
x— это время, аy— сумма заказа, то такая линия показывает общий тренд: суммы заказов со временем растут, падают или стоят примерно на месте.Главная польза в том, что всё считается прямо в базе. Не нужно выгружать данные в Excel, Python или BI-систему, если нужен быстрый тренд или грубый прогноз.
Что делают REGR_SLOPE и REGR_INTERCEPT
Функция
REGR_SLOPE(y, x)возвращает наклон прямой.Наклон отвечает на вопрос:
Функция
REGR_INTERCEPT(y, x)возвращает свободный коэффициент, то есть значение линии приx = 0.Вместе они дают готовую формулу:
Допустим, у нас есть заказы. Мы хотим понять, как сумма оплаченного заказа меняется со временем.
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';Здесь:
amount— этоy, сумма заказа;extract(epoch from created_at)— этоx, дата заказа, превращённая в число;REGR_COUNTпоказывает, сколько пар значений реально попало в расчёт.Дата сама по себе не подходит для регрессии, потому что функции нужны числовые оси. Поэтому мы превращаем дату в количество секунд с начала Unix-эпохи.
Главное правило: сначала y, потом x
Самая частая ошибка с
REGR_SLOPEиREGR_INTERCEPT— перепутать порядок аргументов.В обычной речи мы часто говорим «икс и игрек». Из школы тоже помним: сначала
x, потомy.Но в PostgreSQL порядок другой:
REGR_SLOPE(y, x) REGR_INTERCEPT(y, x)Сначала идёт зависимая переменная — то, что мы изучаем или предсказываем.
Потом идёт независимая переменная — то, от чего зависит показатель.
Например:
REGR_SLOPE(amount, extract(epoch from created_at))Читается так:
А вот так писать не надо:
REGR_SLOPE(extract(epoch from created_at), amount)Такой запрос не упадёт с ошибкой. Он просто посчитает другую зависимость: как время зависит от суммы заказа. Для нашей задачи это бессмыслица, но PostgreSQL не знает вашего бизнес-смысла и честно вернёт число.
Поэтому держите в голове простую фразу:
Пример: тренд суммы заказа по дням
Посмотрим, растёт ли сумма оплаченных заказов со временем.
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';Почему мы умножаем на
86400?Потому что
extract(epoch from created_at)возвращает время в секундах. Значит, самREGR_SLOPEпокажет изменение суммы за одну секунду. Это почти невозможно нормально прочитать.В сутках
86400секунд, поэтому после умножения мы получаем более понятный показатель:Если
amount_per_dayположительный, суммы заказов в среднем растут.Если отрицательный — снижаются.
Если близок к нулю — выраженного линейного тренда почти нет.
Но обязательно смотрите на
sample_size. Если линия построена по трём заказам, это ещё не тренд. Это просто три точки, которые могли случайно лечь как угодно.Пример: прогноз на будущую дату
Раз у нас есть
slopeиintercept, можно подставить будущийxв формулу прямой.Сначала посчитаем коэффициенты в CTE, а потом сделаем прогноз на конкретную дату.
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;Здесь происходит ровно то же самое, что в школьной формуле прямой:
Только
x— это будущая дата, превращённая в число.Важно понимать: это не магический искусственный интеллект и не полноценная модель продаж. Это простая прямая линия. Она полезна для быстрой оценки направления, но не знает про сезонность, акции, праздники, кризисы, отпускной сезон и внезапный вирусный пост в соцсетях.
Пример: зависимость зарплаты от количества подчинённых
Ось
xне обязана быть временем. Это может быть любое числовое значение.Допустим, мы хотим оценить, как зарплата сотрудника связана с количеством людей, которые ему подчиняются.
Сначала посчитаем для каждого сотрудника количество подчинённых, а потом построим регрессию отдельно по отделам.
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;Что здесь означает результат:
salary_per_report— насколько в среднем меняется зарплата при увеличении числа подчинённых на одного человека;base_salary— значение линии при нуле подчинённых;dept— отдел, внутри которого мы строим зависимость.Например, если в одном отделе
salary_per_reportзаметно выше, чем в другом, это может означать, что управленческая нагрузка там сильнее связана с зарплатой. Но это не доказывает причинно-следственную связь. Регрессия показывает зависимость в данных, а не объясняет, почему именно она появилась.Как проверить, можно ли доверять линии
REGR_SLOPEвсегда пытается провести прямую, если для этого хватает данных. Но сама по себе прямая ещё не означает, что зависимость хорошая.Представьте облако точек, разбросанных как попало. Через них всё равно можно провести линию. Вопрос в другом: описывает ли эта линия данные хоть сколько-нибудь нормально?
Для проверки в PostgreSQL есть
REGR_R2иCORR.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';REGR_R2показывает, насколько хорошо линейная модель объясняет разброс данных. Значение находится в диапазоне от0до1.Примерная бытовая интерпретация такая:
0— линия почти ничего не объясняет;1— точки лучше ложатся на прямую;CORRпоказывает корреляцию между двумя числовыми значениями. Она может быть от-1до1.1— сильная положительная связь;-1— сильная отрицательная связь;0— линейной связи почти нет.Например, если
REGR_SLOPEпоказывает рост, ноREGR_R2почти равен нулю, радоваться рано. Формально наклон есть, но линия плохо описывает данные.Что происходит с NULL
Регрессионные функции работают только с парами значений, где оба аргумента не равны
NULL.Например, такая строка попадёт в расчёт:
А такие строки будут пропущены:
Именно поэтому рядом с регрессией полезно выводить
REGR_COUNT.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 sample_size FROM orders WHERE status = 'paid';COUNT(*)покажет все строки после фильтра.А
REGR_COUNT(y, x)покажет только те строки, где одновременно есть иy, иx.Для аналитики это важная разница. Можно думать, что вы строите тренд по десяти тысячам заказов, а на самом деле в расчёт попали только двести строк, потому что в остальных не было суммы или даты.
Когда REGR_SLOPE вернёт NULL
Иногда результатом будет
NULL, и это нормально.Например, если все значения
xодинаковые, наклон посчитать невозможно.Представьте таблицу, где у всех заказов одна и та же дата. Тогда по оси
xнет движения. Нельзя сказать, как меняетсяyпри измененииx, потому чтоxвообще не меняется.В такой ситуации
REGR_SLOPEвернётNULL.То же самое возможно, если после исключения
NULLосталось слишком мало пригодных пар данных.Поэтому в практических запросах хорошо смотреть сразу несколько показателей:
SELECT REGR_COUNT(amount, extract(epoch from created_at)) AS sample_size, REGR_SLOPE(amount, extract(epoch from created_at)) AS slope, REGR_INTERCEPT(amount, extract(epoch from created_at)) AS intercept, REGR_R2(amount, extract(epoch from created_at)) AS r_squared FROM orders WHERE status = 'paid';Так вы видите не только саму линию, но и то, насколько вообще прилично её было строить.
Линейная регрессия видит только прямую
У
REGR_SLOPEиREGR_INTERCEPTесть важное ограничение: они подбирают прямую линию.А жизнь часто устроена сложнее.
Например:
Линейная регрессия всё это не понимает. Она берёт облако точек и проводит через него одну прямую.
Поэтому такие функции хороши для первого взгляда на данные:
Но для серьёзного прогноза обычно нужны дополнительные проверки, сегментация, сезонность и понимание бизнеса.
Чем REGR_SLOPE отличается от обычных агрегатов
Обычные агрегаты отвечают на простые вопросы:
SELECT count(*) AS orders_count, sum(amount) AS total_amount, avg(amount) AS avg_amount FROM orders WHERE status = 'paid';Такой запрос говорит:
Но он не говорит, куда движется показатель.
А регрессионные функции отвечают уже на другой вопрос:
SELECT REGR_SLOPE(amount, extract(epoch from created_at)) * 86400 AS amount_per_day FROM orders WHERE status = 'paid';Этот запрос спрашивает:
То есть
SUM,AVGиCOUNTописывают состояние.А
REGR_SLOPEпомогает увидеть направление.Как это выглядит в аналитической задаче
Допустим, аналитик смотрит на оплаченные заказы и хочет быстро понять, есть ли рост среднего размера заказа.
Можно собрать компактный отчёт:
SELECT REGR_COUNT(amount, extract(epoch from created_at)) AS sample_size, avg(amount) AS avg_amount, REGR_SLOPE(amount, extract(epoch from created_at)) * 86400 AS amount_per_day, 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';Такой запрос даёт сразу несколько уровней понимания:
sample_size— сколько точек участвовало в расчёте;avg_amount— средний размер оплаченного заказа;amount_per_day— примерное изменение суммы заказа за день;r_squared— насколько хорошо прямая описывает данные;correlation— насколько сильна линейная связь.Это уже похоже не на голое число, а на маленький аналитический вывод прямо из SQL.
Отличия в других СУБД
В PostgreSQL порядок аргументов такой:
REGR_SLOPE(y, x) REGR_INTERCEPT(y, x)То есть сначала показатель, потом объясняющая переменная.
В других СУБД ситуация может отличаться.
В MySQL функций семейства
REGR_*нет. Наклон и свободный коэффициент обычно считают вручную черезSUM,AVGи формулы линейной регрессии.Формула наклона выглядит так:
А свободный коэффициент так:
В ClickHouse есть функция
simpleLinearRegression(x, y). У неё порядок аргументов обратный по сравнению с PostgreSQL: сначалаx, потомy. Функция возвращает пару значений: наклон и свободный коэффициент.В BigQuery встроенных
REGR_SLOPEиREGR_INTERCEPTнет. Там коэффициенты можно посчитать вручную через агрегаты вродеSUM,AVG,COVAR_POPиVAR_POP, либо использовать BigQuery ML и обучать модель черезCREATE MODEL.В Snowflake функции
REGR_SLOPE(y, x)иREGR_INTERCEPT(y, x)поддерживаются в привычном для PostgreSQL порядке.Главный вывод простой: при переходе между СУБД всегда проверяйте порядок аргументов. Ошибка не обязательно сломает запрос, но может полностью испортить смысл результата.
Главное из статьи
REGR_SLOPEиREGR_INTERCEPTв PostgreSQL позволяют построить простую линию тренда прямо в SQL.Они возвращают коэффициенты для формулы:
Главное правило — не перепутать аргументы:
REGR_SLOPE(y, x) REGR_INTERCEPT(y, x)Сначала идёт то, что мы предсказываем или изучаем. Потом — то, от чего это зависит.
Для дат и времени ось
xнужно превращать в число, например черезextract(epoch from created_at).Рядом с регрессией почти всегда полезно выводить
REGR_COUNT, потому что строки сNULLвyилиxне участвуют в расчёте.Чтобы понять, насколько линии можно доверять, смотрите на
REGR_R2иCORR.И самое важное: линейная регрессия — это быстрый способ увидеть общее направление, а не универсальная машина предсказаний. Она отлично подходит для первого анализа, но требует здравого смысла, проверки качества и понимания данных.