Один наклон сам по себе ещё ничего не доказывает.
Запрос может честно посчитать, что выручка растёт. Функция REGR_SLOPE покажет положительный наклон, и на первый взгляд всё выглядит приятно: линия идёт вверх, бизнес развивается, можно радоваться.
Но есть подвох.
Иногда точки на графике разбросаны как попало: сегодня выручка высокая, завтра низкая, послезавтра снова скачок, потом провал. Если через такое облако точек провести прямую, она тоже может оказаться чуть наклонённой вверх. Формально рост есть. По смыслу — почти никакой закономерности нет.
Вот здесь и нужна функция REGR_R2.
Она отвечает на вопрос:
Насколько хорошо прямая линия вообще объясняет данные?
REGR_SLOPE говорит, куда направлен тренд.
REGR_R2 говорит, стоит ли этому тренду доверять.
Что такое REGR_R2
REGR_R2 возвращает коэффициент детерминации, его ещё называют R-squared.
Это число от 0 до 1.
Оно показывает, какую долю разброса зависимой переменной объясняет линейная модель.
Звучит академично, но смысл простой.
Представьте, что у нас есть точки на графике:
- по горизонтали — время;
- по вертикали — выручка.
Мы проводим через эти точки прямую линию тренда. REGR_R2 показывает, насколько эта линия удачно легла на данные.
Если точки почти лежат на прямой, значение будет близко к 1.
Если точки разбросаны хаотично, значение будет близко к 0.
Синтаксис
Синтаксис такой:
SELECT
REGR_R2(y, x) AS r2
FROM points;
Порядок аргументов важен:
REGR_R2(y, x)
Сначала идёт зависимая переменная y.
Потом независимая переменная x.
Проще говоря:
y — что мы пытаемся объяснить или предсказать;
x — с помощью чего мы это объясняем.
Например:
REGR_R2(revenue, day_number)
Здесь мы спрашиваем:
Насколько хорошо день объясняет выручку?
То есть есть ли линейная связь между временем и выручкой.
Если перепутать аргументы местами, запрос может выполниться, но смысл получится другой. Поэтому привычка такая: сначала результат, потом фактор.
Как читать R-квадрат
Ориентиры такие:
| Значение |
Как понимать |
1.0 |
идеальная линейная связь, точки лежат на прямой |
0.8 |
сильная линейная связь, тренд выглядит надёжно |
0.4 |
часть разброса объясняется линией, но шума много |
0.05 |
линия почти ничего не объясняет |
0.0 |
линейной связи нет |
Важно не превращать эти числа в магические правила.
В одних задачах 0.3 уже может быть полезным сигналом. В других даже 0.7 может быть мало. Но для учебных и аналитических отчётов полезная интуиция такая:
чем ближе REGR_R2 к 1, тем лучше линия описывает данные; чем ближе к 0, тем больше перед нами шум.
Простая интуиция: сравнение с ленивой моделью
Представьте самую ленивую модель на свете.
Она вообще не смотрит на x.
Она всегда говорит:
Я предсказываю среднее значение y.
Например, если средняя дневная выручка равна 10000, такая модель каждый день предсказывает 10000.
Линейная регрессия пытается быть умнее. Она строит прямую и говорит:
В начале периода ожидаю меньше, в конце больше.
И REGR_R2 показывает, насколько эта прямая лучше ленивого среднего.
Если лучше почти никак — R-squared будет около 0.
Если прямая объясняет большую часть разброса — значение будет ближе к 1.
Проверяем тренд выручки
Возьмём задачу из жизни.
Есть таблица orders. В ней лежат заказы, суммы и даты создания. Нужно понять, правда ли выручка растёт со временем.
Сначала соберём дневную выручку, а потом посчитаем наклон и R-squared.
WITH daily AS (
SELECT
date_trunc('day', created_at) AS day,
SUM(amount) AS revenue
FROM orders
WHERE status = 'paid'
GROUP BY 1
)
SELECT
REGR_SLOPE(revenue, EXTRACT(EPOCH FROM day)) AS slope,
REGR_R2(revenue, EXTRACT(EPOCH FROM day)) AS r2,
COUNT(*) AS days
FROM daily;
Что здесь происходит:
- В
daily мы собираем выручку по дням.
REGR_SLOPE считает наклон линии.
REGR_R2 показывает, насколько хорошо эта линия объясняет дневную выручку.
COUNT(*) показывает, сколько дней попало в расчёт.
Почему в качестве x используется EXTRACT(EPOCH FROM day)?
Потому что регрессии нужны числа. Дата сама по себе — это дата, а не числовая ось. EXTRACT(EPOCH FROM day) превращает день в количество секунд, прошедших с начала Unix-эпохи.
Для тренда это удобно: время становится числом, и по нему можно строить линейную регрессию.
Как интерпретировать результат
Допустим, запрос вернул:
| slope |
r2 |
days |
0.02 |
0.04 |
60 |
Наклон положительный. Формально линия идёт вверх.
Но r2 = 0.04. Это значит, что линия объясняет примерно 4% разброса выручки. Остальное — шум, случайные скачки, акции, выходные, крупные клиенты, сезонность и всё что угодно.
Такой результат опасно продавать как «выручка уверенно растёт».
Правильнее сказать:
Наклон положительный, но качество линейного тренда слабое. По этим данным устойчивый рост не подтверждается.
А теперь другой результат:
| slope |
r2 |
days |
0.02 |
0.82 |
60 |
Здесь тоже положительный наклон, но теперь r2 = 0.82.
Это уже гораздо сильнее. Линия объясняет большую часть разброса дневной выручки. Такой тренд выглядит намного надёжнее.
Почему REGR_SLOPE нужно читать вместе с REGR_R2
REGR_SLOPE и REGR_R2 отвечают на разные вопросы.
REGR_SLOPE:
В какую сторону и насколько сильно наклонена линия?
REGR_R2:
Насколько хорошо эта линия описывает точки?
Без REGR_R2 можно легко обмануться.
Например:
| slope |
r2 |
Что это значит |
100 |
0.02 |
линия крутая, но данные шумные, доверия мало |
5 |
0.95 |
рост слабый, зато очень устойчивый |
-20 |
0.8 |
есть заметный и довольно надёжный спад |
0 |
0.0 |
линейного тренда нет |
Крутой наклон не всегда означает хороший тренд.
Пологий наклон не всегда означает бесполезный тренд.
Сначала смотрим на направление и величину через REGR_SLOPE, потом проверяем доверие через REGR_R2.
Пример с продажами по странам
Сила REGR_R2 особенно хорошо видна в группировках.
Например, мы хотим понять, в каких странах сумма заказов со временем растёт более устойчиво, а где всё похоже на шум.
SELECT
u.country,
REGR_SLOPE(o.amount, EXTRACT(EPOCH FROM o.created_at)) AS slope,
REGR_R2(o.amount, EXTRACT(EPOCH FROM o.created_at)) AS r2,
COUNT(*) AS orders_count
FROM orders o
JOIN users u ON u.id = o.user_id
WHERE o.status = 'paid'
GROUP BY u.country
HAVING COUNT(*) >= 30
ORDER BY r2 DESC;
Здесь мы считаем отдельную линейную регрессию для каждой страны.
В результате можно увидеть, например:
| country |
slope |
r2 |
orders_count |
| Germany |
0.015 |
0.78 |
240 |
| Spain |
0.010 |
0.55 |
180 |
| Italy |
0.030 |
0.08 |
95 |
Что это значит?
У Германии тренд выглядит устойчиво: r2 высокий.
У Испании связь средняя: что-то есть, но шум тоже заметный.
У Италии наклон самый большой, но r2 очень низкий. Значит, красивая цифра slope может быть случайной. Там данные сильно скачут, и линия плохо объясняет происходящее.
Зачем нужен HAVING COUNT(*) >= 30
В предыдущем запросе есть важная строка:
HAVING COUNT(*) >= 30
Это не украшение. Это защита от маленьких групп.
На двух точках прямая может пройти идеально. Поэтому для двух точек линейная связь может выглядеть подозрительно прекрасной.
Например, в стране было всего два заказа:
| date |
amount |
| 2026-01-01 |
100 |
| 2026-01-02 |
300 |
Через эти две точки легко провести прямую. Значение R-squared может получиться идеальным или почти идеальным, но такой вывод не стоит доверия.
Две точки — это не тренд. Это просто две точки.
Поэтому перед анализом сегментов полезно ставить минимальный порог:
HAVING COUNT(*) >= 30
Число 30 не является законом природы. В реальной аналитике порог зависит от задачи. Но сама идея обязательна: не сравнивайте качество тренда на крошечных выборках с нормальными сегментами.
REGR_R2 и CORR
Для простой линейной регрессии с одной независимой переменной есть полезная связь:
REGR_R2(y, x)
равен квадрату корреляции Пирсона:
POWER(CORR(y, x), 2)
Можно проверить это запросом:
SELECT
REGR_R2(salary, manager_id) AS r2,
POWER(CORR(salary, manager_id), 2) AS corr_squared
FROM employees
WHERE manager_id IS NOT NULL;
Оба значения должны совпасть с небольшой погрешностью из-за вычислений с числами с плавающей точкой.
Но пример с manager_id специально выглядит немного странно. manager_id — это идентификатор, а не настоящая числовая причина зарплаты. Формально посчитать можно, но смысл такого анализа сомнительный.
Это важный урок:
SQL посчитает формулу для любых чисел, но думать о смысле данных всё равно должен человек.
R-квадрат показывает только линейную связь
REGR_R2 оценивает именно линейную зависимость.
То есть он хорошо отвечает на вопрос:
Похожи ли данные на прямую линию?
Но связь между переменными не всегда прямая.
Например, зависимость может быть такой:
- сначала рост быстрый, потом замедляется;
- есть сезонные волны;
- данные похожи на параболу;
- после определённой точки начинается резкий скачок;
- по будням одно поведение, по выходным другое.
В таких случаях R-squared может быть низким, хотя связь между переменными действительно есть. Просто она не линейная.
Очень простой пример: идеальная парабола. Между x и y есть железная связь, но прямая линия может описывать её плохо.
Поэтому низкий REGR_R2 означает не «связи нет вообще», а:
линейная модель плохо объясняет эти данные.
Это разные вещи.
Высокий R-квадрат не доказывает причинность
Ещё одна ловушка: высокий REGR_R2 не означает, что x вызывает y.
Он означает только одно:
прямая линия хорошо описывает связь между x и y.
Например, две метрики могут одновременно расти из-за третьей причины.
Продажи мороженого и продажи лимонада могут расти вместе. Но это не значит, что мороженое вызывает лимонад. Скорее всего, обе метрики растут из-за жары.
В бизнес-данных такое встречается постоянно:
- выручка растёт вместе с количеством пользователей;
- количество ошибок растёт вместе с трафиком;
- нагрузка на поддержку растёт вместе с числом заказов;
- расходы на рекламу растут вместе с продажами.
REGR_R2 помогает заметить линейную связь, но не объясняет причину этой связи.
NULL в REGR_R2
Как и другие агрегатные функции регрессии, REGR_R2 игнорирует строки, где x или y равны NULL.
Например:
SELECT
REGR_R2(revenue, visitors) AS r2
FROM daily_metrics;
Если в строке нет revenue или нет visitors, эта пара не попадёт в расчёт.
Это логично: для точки на графике нужны обе координаты.
Но в отчётах из-за этого можно получить неожиданность. Вы думаете, что считаете по 100 дням, а реально в расчёт попало 63 дня.
Поэтому рядом полезно выводить количество строк:
SELECT
REGR_R2(revenue, visitors) AS r2,
COUNT(*) AS rows_total,
COUNT(revenue) AS revenue_count,
COUNT(visitors) AS visitors_count,
REGR_COUNT(revenue, visitors) AS pairs_count
FROM daily_metrics;
REGR_COUNT показывает, сколько пар значений реально участвовало в регрессии.
Это особенно полезно, когда данные собраны из разных источников и в них много пропусков.
Пример: связь выручки и числа посетителей
Допустим, у нас есть таблица дневных метрик:
Хотим понять, насколько хорошо количество посетителей объясняет выручку.
SELECT
REGR_SLOPE(revenue, visitors) AS slope,
REGR_R2(revenue, visitors) AS r2,
REGR_COUNT(revenue, visitors) AS pairs_count
FROM daily_metrics;
Если результат такой:
| slope |
r2 |
pairs_count |
12.5 |
0.88 |
90 |
это можно прочитать так:
Чем больше посетителей, тем выше выручка. Связь выглядит сильной и достаточно устойчивой.
Но если результат такой:
| slope |
r2 |
pairs_count |
12.5 |
0.10 |
90 |
наклон вроде тот же, но доверия намного меньше.
Возможно, на выручку сильно влияют не только посетители, но и скидки, источник трафика, день недели, сезонность, средний чек или крупные разовые покупки.
REGR_R2 в HAVING
Иногда удобно сразу отфильтровать группы, где линейная связь слабая.
Например, хотим показать только страны, где тренд по заказам выглядит достаточно уверенно:
SELECT
u.country,
REGR_SLOPE(o.amount, EXTRACT(EPOCH FROM o.created_at)) AS slope,
REGR_R2(o.amount, EXTRACT(EPOCH FROM o.created_at)) AS r2,
REGR_COUNT(o.amount, EXTRACT(EPOCH FROM o.created_at)) AS pairs_count
FROM orders o
JOIN users u ON u.id = o.user_id
WHERE o.status = 'paid'
GROUP BY u.country
HAVING
REGR_COUNT(o.amount, EXTRACT(EPOCH FROM o.created_at)) >= 30
AND REGR_R2(o.amount, EXTRACT(EPOCH FROM o.created_at)) >= 0.6
ORDER BY r2 DESC;
Такой запрос оставит только сегменты, где:
- достаточно данных;
- линейная модель объясняет заметную часть разброса.
Но будьте аккуратны: фильтр по r2 — это не истина в последней инстанции. Он помогает убрать шумные сегменты, но окончательный вывод всё равно зависит от задачи.
Почему полезно смотреть на график
SQL хорошо считает числа. Но числа не всегда рассказывают всю историю.
Перед важным выводом полезно построить график точек:
x по горизонтали;
y по вертикали;
- сверху линия тренда.
Почему это важно?
Потому что REGR_R2 может не показать некоторые особенности:
- выбросы;
- кластеры;
- сезонность;
- резкий перелом в середине периода;
- нелинейную зависимость;
- разные группы, смешанные в одну.
Например, общий тренд по всем пользователям может быть слабым. А если разделить пользователей по странам или тарифам, внутри каждой группы связь окажется сильной.
SQL даст вам первую проверку. График поможет понять, что именно происходит.
Производительность
REGR_R2 — агрегатная функция. Она считает значение по группе строк.
Если вы считаете один общий показатель по таблице, PostgreSQL проходит по подходящим строкам и агрегирует их.
Если используете GROUP BY, отдельный расчёт делается для каждой группы.
Например:
SELECT
country,
REGR_R2(revenue, visitors) AS r2
FROM daily_country_metrics
GROUP BY country;
Здесь регрессия считается отдельно для каждой страны.
На больших таблицах важны обычные вещи:
- фильтруйте лишние строки в
WHERE;
- заранее агрегируйте сырые события до нужного уровня;
- не считайте тренд по миллионам событий, если вам нужен тренд по дням;
- проверяйте запрос через
EXPLAIN ANALYZE.
Частая ошибка — считать регрессию прямо по отдельным заказам, когда на самом деле нужен тренд дневной выручки. Тогда сначала нужно собрать данные по дням, как в примере с daily, и только потом применять REGR_R2.
Переносимость
REGR_R2 есть в PostgreSQL, но не во всех популярных СУБД.
В MySQL стандартного аналога REGR_R2 нет. Там такой показатель обычно собирают вручную через корреляцию, дисперсии или промежуточные агрегаты.
В ClickHouse прямого REGR_R2 тоже может не быть в привычном PostgreSQL-виде, но похожий расчёт можно собрать через статистические агрегаты и формулы.
Если вы пишете именно под PostgreSQL, REGR_R2 удобен тем, что всё уже встроено и читается прямо в SQL.
Если запрос должен быть переносимым между разными базами, лучше заранее проверить поддержку регрессионных функций в нужной СУБД.
Частые ошибки
Первая ошибка — смотреть только на REGR_SLOPE.
SELECT
REGR_SLOPE(revenue, visitors) AS slope
FROM daily_metrics;
Так вы видите направление, но не видите качество связи. Лучше сразу добавлять REGR_R2.
SELECT
REGR_SLOPE(revenue, visitors) AS slope,
REGR_R2(revenue, visitors) AS r2
FROM daily_metrics;
Вторая ошибка — забывать про размер выборки.
SELECT
country,
REGR_R2(amount, EXTRACT(EPOCH FROM created_at)) AS r2
FROM orders
GROUP BY country
ORDER BY r2 DESC;
Без проверки количества строк наверх могут попасть страны с двумя-тремя заказами. Формально r2 там может быть красивым, но доверять ему нельзя.
Лучше так:
SELECT
country,
REGR_R2(amount, EXTRACT(EPOCH FROM created_at)) AS r2,
REGR_COUNT(amount, EXTRACT(EPOCH FROM created_at)) AS pairs_count
FROM orders
GROUP BY country
HAVING REGR_COUNT(amount, EXTRACT(EPOCH FROM created_at)) >= 30
ORDER BY r2 DESC;
Третья ошибка — считать высокий r2 доказательством причины.
R-squared говорит о качестве линейного описания, а не о том, что одно явление вызывает другое.
Четвёртая ошибка — делать вывод «связи нет», если r2 низкий.
Правильнее сказать:
Линейной связи почти нет.
Связь может быть нелинейной, сезонной или проявляться только внутри отдельных сегментов.
Главное
REGR_R2 в PostgreSQL показывает, насколько хорошо линейная регрессия объясняет данные.
Синтаксис:
SELECT
REGR_R2(y, x) AS r2
FROM points;
Сначала пишем зависимую переменную y, потом независимую переменную x.
REGR_R2 возвращает число от 0 до 1:
- ближе к
1 — точки хорошо ложатся на прямую;
- ближе к
0 — прямая почти не объясняет разброс данных.
REGR_SLOPE и REGR_R2 лучше всегда считать вместе:
SELECT
REGR_SLOPE(revenue, visitors) AS slope,
REGR_R2(revenue, visitors) AS r2
FROM daily_metrics;
REGR_SLOPE показывает направление и величину изменения.
REGR_R2 показывает, насколько этому наклону можно доверять.
Высокий R-squared не доказывает причинность. Низкий R-squared не доказывает отсутствие любой связи. Он говорит только о том, насколько хорошо данные описываются прямой линией.
Практическое правило простое: если вы показываете тренд в отчёте, не ограничивайтесь наклоном. Добавляйте REGR_R2, количество наблюдений и, если решение важное, обязательно смотрите на график. Тогда вместо красивой, но случайной линии у вас появится нормальная аналитическая проверка.
Один наклон сам по себе ещё ничего не доказывает.
Запрос может честно посчитать, что выручка растёт. Функция
REGR_SLOPEпокажет положительный наклон, и на первый взгляд всё выглядит приятно: линия идёт вверх, бизнес развивается, можно радоваться.Но есть подвох.
Иногда точки на графике разбросаны как попало: сегодня выручка высокая, завтра низкая, послезавтра снова скачок, потом провал. Если через такое облако точек провести прямую, она тоже может оказаться чуть наклонённой вверх. Формально рост есть. По смыслу — почти никакой закономерности нет.
Вот здесь и нужна функция
REGR_R2.Она отвечает на вопрос:
REGR_SLOPEговорит, куда направлен тренд.REGR_R2говорит, стоит ли этому тренду доверять.Что такое REGR_R2
REGR_R2возвращает коэффициент детерминации, его ещё называютR-squared.Это число от
0до1.Оно показывает, какую долю разброса зависимой переменной объясняет линейная модель.
Звучит академично, но смысл простой.
Представьте, что у нас есть точки на графике:
Мы проводим через эти точки прямую линию тренда.
REGR_R2показывает, насколько эта линия удачно легла на данные.Если точки почти лежат на прямой, значение будет близко к
1.Если точки разбросаны хаотично, значение будет близко к
0.Синтаксис
Синтаксис такой:
SELECT REGR_R2(y, x) AS r2 FROM points;Порядок аргументов важен:
REGR_R2(y, x)Сначала идёт зависимая переменная
y.Потом независимая переменная
x.Проще говоря:
y— что мы пытаемся объяснить или предсказать;x— с помощью чего мы это объясняем.Например:
REGR_R2(revenue, day_number)Здесь мы спрашиваем:
То есть есть ли линейная связь между временем и выручкой.
Если перепутать аргументы местами, запрос может выполниться, но смысл получится другой. Поэтому привычка такая: сначала результат, потом фактор.
Как читать R-квадрат
Ориентиры такие:
1.00.80.40.050.0Важно не превращать эти числа в магические правила.
В одних задачах
0.3уже может быть полезным сигналом. В других даже0.7может быть мало. Но для учебных и аналитических отчётов полезная интуиция такая:Простая интуиция: сравнение с ленивой моделью
Представьте самую ленивую модель на свете.
Она вообще не смотрит на
x.Она всегда говорит:
Например, если средняя дневная выручка равна
10000, такая модель каждый день предсказывает10000.Линейная регрессия пытается быть умнее. Она строит прямую и говорит:
И
REGR_R2показывает, насколько эта прямая лучше ленивого среднего.Если лучше почти никак —
R-squaredбудет около0.Если прямая объясняет большую часть разброса — значение будет ближе к
1.Проверяем тренд выручки
Возьмём задачу из жизни.
Есть таблица
orders. В ней лежат заказы, суммы и даты создания. Нужно понять, правда ли выручка растёт со временем.Сначала соберём дневную выручку, а потом посчитаем наклон и
R-squared.WITH daily AS ( SELECT date_trunc('day', created_at) AS day, SUM(amount) AS revenue FROM orders WHERE status = 'paid' GROUP BY 1 ) SELECT REGR_SLOPE(revenue, EXTRACT(EPOCH FROM day)) AS slope, REGR_R2(revenue, EXTRACT(EPOCH FROM day)) AS r2, COUNT(*) AS days FROM daily;Что здесь происходит:
dailyмы собираем выручку по дням.REGR_SLOPEсчитает наклон линии.REGR_R2показывает, насколько хорошо эта линия объясняет дневную выручку.COUNT(*)показывает, сколько дней попало в расчёт.Почему в качестве
xиспользуетсяEXTRACT(EPOCH FROM day)?Потому что регрессии нужны числа. Дата сама по себе — это дата, а не числовая ось.
EXTRACT(EPOCH FROM day)превращает день в количество секунд, прошедших с начала Unix-эпохи.Для тренда это удобно: время становится числом, и по нему можно строить линейную регрессию.
Как интерпретировать результат
Допустим, запрос вернул:
0.020.0460Наклон положительный. Формально линия идёт вверх.
Но
r2 = 0.04. Это значит, что линия объясняет примерно 4% разброса выручки. Остальное — шум, случайные скачки, акции, выходные, крупные клиенты, сезонность и всё что угодно.Такой результат опасно продавать как «выручка уверенно растёт».
Правильнее сказать:
А теперь другой результат:
0.020.8260Здесь тоже положительный наклон, но теперь
r2 = 0.82.Это уже гораздо сильнее. Линия объясняет большую часть разброса дневной выручки. Такой тренд выглядит намного надёжнее.
Почему REGR_SLOPE нужно читать вместе с REGR_R2
REGR_SLOPEиREGR_R2отвечают на разные вопросы.REGR_SLOPE:REGR_R2:Без
REGR_R2можно легко обмануться.Например:
1000.0250.95-200.800.0Крутой наклон не всегда означает хороший тренд.
Пологий наклон не всегда означает бесполезный тренд.
Сначала смотрим на направление и величину через
REGR_SLOPE, потом проверяем доверие черезREGR_R2.Пример с продажами по странам
Сила
REGR_R2особенно хорошо видна в группировках.Например, мы хотим понять, в каких странах сумма заказов со временем растёт более устойчиво, а где всё похоже на шум.
SELECT u.country, REGR_SLOPE(o.amount, EXTRACT(EPOCH FROM o.created_at)) AS slope, REGR_R2(o.amount, EXTRACT(EPOCH FROM o.created_at)) AS r2, COUNT(*) AS orders_count FROM orders o JOIN users u ON u.id = o.user_id WHERE o.status = 'paid' GROUP BY u.country HAVING COUNT(*) >= 30 ORDER BY r2 DESC;Здесь мы считаем отдельную линейную регрессию для каждой страны.
В результате можно увидеть, например:
0.0150.782400.0100.551800.0300.0895Что это значит?
У Германии тренд выглядит устойчиво:
r2высокий.У Испании связь средняя: что-то есть, но шум тоже заметный.
У Италии наклон самый большой, но
r2очень низкий. Значит, красивая цифраslopeможет быть случайной. Там данные сильно скачут, и линия плохо объясняет происходящее.Зачем нужен HAVING COUNT(*) >= 30
В предыдущем запросе есть важная строка:
HAVING COUNT(*) >= 30Это не украшение. Это защита от маленьких групп.
На двух точках прямая может пройти идеально. Поэтому для двух точек линейная связь может выглядеть подозрительно прекрасной.
Например, в стране было всего два заказа:
100300Через эти две точки легко провести прямую. Значение
R-squaredможет получиться идеальным или почти идеальным, но такой вывод не стоит доверия.Две точки — это не тренд. Это просто две точки.
Поэтому перед анализом сегментов полезно ставить минимальный порог:
HAVING COUNT(*) >= 30Число
30не является законом природы. В реальной аналитике порог зависит от задачи. Но сама идея обязательна: не сравнивайте качество тренда на крошечных выборках с нормальными сегментами.REGR_R2 и CORR
Для простой линейной регрессии с одной независимой переменной есть полезная связь:
REGR_R2(y, x)равен квадрату корреляции Пирсона:
POWER(CORR(y, x), 2)Можно проверить это запросом:
SELECT REGR_R2(salary, manager_id) AS r2, POWER(CORR(salary, manager_id), 2) AS corr_squared FROM employees WHERE manager_id IS NOT NULL;Оба значения должны совпасть с небольшой погрешностью из-за вычислений с числами с плавающей точкой.
Но пример с
manager_idспециально выглядит немного странно.manager_id— это идентификатор, а не настоящая числовая причина зарплаты. Формально посчитать можно, но смысл такого анализа сомнительный.Это важный урок:
R-квадрат показывает только линейную связь
REGR_R2оценивает именно линейную зависимость.То есть он хорошо отвечает на вопрос:
Но связь между переменными не всегда прямая.
Например, зависимость может быть такой:
В таких случаях
R-squaredможет быть низким, хотя связь между переменными действительно есть. Просто она не линейная.Очень простой пример: идеальная парабола. Между
xиyесть железная связь, но прямая линия может описывать её плохо.Поэтому низкий
REGR_R2означает не «связи нет вообще», а:Это разные вещи.
Высокий R-квадрат не доказывает причинность
Ещё одна ловушка: высокий
REGR_R2не означает, чтоxвызываетy.Он означает только одно:
Например, две метрики могут одновременно расти из-за третьей причины.
Продажи мороженого и продажи лимонада могут расти вместе. Но это не значит, что мороженое вызывает лимонад. Скорее всего, обе метрики растут из-за жары.
В бизнес-данных такое встречается постоянно:
REGR_R2помогает заметить линейную связь, но не объясняет причину этой связи.NULL в REGR_R2
Как и другие агрегатные функции регрессии,
REGR_R2игнорирует строки, гдеxилиyравныNULL.Например:
SELECT REGR_R2(revenue, visitors) AS r2 FROM daily_metrics;Если в строке нет
revenueили нетvisitors, эта пара не попадёт в расчёт.Это логично: для точки на графике нужны обе координаты.
Но в отчётах из-за этого можно получить неожиданность. Вы думаете, что считаете по 100 дням, а реально в расчёт попало 63 дня.
Поэтому рядом полезно выводить количество строк:
SELECT REGR_R2(revenue, visitors) AS r2, COUNT(*) AS rows_total, COUNT(revenue) AS revenue_count, COUNT(visitors) AS visitors_count, REGR_COUNT(revenue, visitors) AS pairs_count FROM daily_metrics;REGR_COUNTпоказывает, сколько пар значений реально участвовало в регрессии.Это особенно полезно, когда данные собраны из разных источников и в них много пропусков.
Пример: связь выручки и числа посетителей
Допустим, у нас есть таблица дневных метрик:
day;visitors;revenue.Хотим понять, насколько хорошо количество посетителей объясняет выручку.
SELECT REGR_SLOPE(revenue, visitors) AS slope, REGR_R2(revenue, visitors) AS r2, REGR_COUNT(revenue, visitors) AS pairs_count FROM daily_metrics;Если результат такой:
12.50.8890это можно прочитать так:
Но если результат такой:
12.50.1090наклон вроде тот же, но доверия намного меньше.
Возможно, на выручку сильно влияют не только посетители, но и скидки, источник трафика, день недели, сезонность, средний чек или крупные разовые покупки.
REGR_R2 в HAVING
Иногда удобно сразу отфильтровать группы, где линейная связь слабая.
Например, хотим показать только страны, где тренд по заказам выглядит достаточно уверенно:
SELECT u.country, REGR_SLOPE(o.amount, EXTRACT(EPOCH FROM o.created_at)) AS slope, REGR_R2(o.amount, EXTRACT(EPOCH FROM o.created_at)) AS r2, REGR_COUNT(o.amount, EXTRACT(EPOCH FROM o.created_at)) AS pairs_count FROM orders o JOIN users u ON u.id = o.user_id WHERE o.status = 'paid' GROUP BY u.country HAVING REGR_COUNT(o.amount, EXTRACT(EPOCH FROM o.created_at)) >= 30 AND REGR_R2(o.amount, EXTRACT(EPOCH FROM o.created_at)) >= 0.6 ORDER BY r2 DESC;Такой запрос оставит только сегменты, где:
Но будьте аккуратны: фильтр по
r2— это не истина в последней инстанции. Он помогает убрать шумные сегменты, но окончательный вывод всё равно зависит от задачи.Почему полезно смотреть на график
SQL хорошо считает числа. Но числа не всегда рассказывают всю историю.
Перед важным выводом полезно построить график точек:
xпо горизонтали;yпо вертикали;Почему это важно?
Потому что
REGR_R2может не показать некоторые особенности:Например, общий тренд по всем пользователям может быть слабым. А если разделить пользователей по странам или тарифам, внутри каждой группы связь окажется сильной.
SQL даст вам первую проверку. График поможет понять, что именно происходит.
Производительность
REGR_R2— агрегатная функция. Она считает значение по группе строк.Если вы считаете один общий показатель по таблице, PostgreSQL проходит по подходящим строкам и агрегирует их.
Если используете
GROUP BY, отдельный расчёт делается для каждой группы.Например:
SELECT country, REGR_R2(revenue, visitors) AS r2 FROM daily_country_metrics GROUP BY country;Здесь регрессия считается отдельно для каждой страны.
На больших таблицах важны обычные вещи:
WHERE;EXPLAIN ANALYZE.Частая ошибка — считать регрессию прямо по отдельным заказам, когда на самом деле нужен тренд дневной выручки. Тогда сначала нужно собрать данные по дням, как в примере с
daily, и только потом применятьREGR_R2.Переносимость
REGR_R2есть в PostgreSQL, но не во всех популярных СУБД.В MySQL стандартного аналога
REGR_R2нет. Там такой показатель обычно собирают вручную через корреляцию, дисперсии или промежуточные агрегаты.В ClickHouse прямого
REGR_R2тоже может не быть в привычном PostgreSQL-виде, но похожий расчёт можно собрать через статистические агрегаты и формулы.Если вы пишете именно под PostgreSQL,
REGR_R2удобен тем, что всё уже встроено и читается прямо в SQL.Если запрос должен быть переносимым между разными базами, лучше заранее проверить поддержку регрессионных функций в нужной СУБД.
Частые ошибки
Первая ошибка — смотреть только на
REGR_SLOPE.SELECT REGR_SLOPE(revenue, visitors) AS slope FROM daily_metrics;Так вы видите направление, но не видите качество связи. Лучше сразу добавлять
REGR_R2.SELECT REGR_SLOPE(revenue, visitors) AS slope, REGR_R2(revenue, visitors) AS r2 FROM daily_metrics;Вторая ошибка — забывать про размер выборки.
SELECT country, REGR_R2(amount, EXTRACT(EPOCH FROM created_at)) AS r2 FROM orders GROUP BY country ORDER BY r2 DESC;Без проверки количества строк наверх могут попасть страны с двумя-тремя заказами. Формально
r2там может быть красивым, но доверять ему нельзя.Лучше так:
SELECT country, REGR_R2(amount, EXTRACT(EPOCH FROM created_at)) AS r2, REGR_COUNT(amount, EXTRACT(EPOCH FROM created_at)) AS pairs_count FROM orders GROUP BY country HAVING REGR_COUNT(amount, EXTRACT(EPOCH FROM created_at)) >= 30 ORDER BY r2 DESC;Третья ошибка — считать высокий
r2доказательством причины.R-squaredговорит о качестве линейного описания, а не о том, что одно явление вызывает другое.Четвёртая ошибка — делать вывод «связи нет», если
r2низкий.Правильнее сказать:
Связь может быть нелинейной, сезонной или проявляться только внутри отдельных сегментов.
Главное
REGR_R2в PostgreSQL показывает, насколько хорошо линейная регрессия объясняет данные.Синтаксис:
SELECT REGR_R2(y, x) AS r2 FROM points;Сначала пишем зависимую переменную
y, потом независимую переменнуюx.REGR_R2возвращает число от0до1:1— точки хорошо ложатся на прямую;0— прямая почти не объясняет разброс данных.REGR_SLOPEиREGR_R2лучше всегда считать вместе:SELECT REGR_SLOPE(revenue, visitors) AS slope, REGR_R2(revenue, visitors) AS r2 FROM daily_metrics;REGR_SLOPEпоказывает направление и величину изменения.REGR_R2показывает, насколько этому наклону можно доверять.Высокий
R-squaredне доказывает причинность. НизкийR-squaredне доказывает отсутствие любой связи. Он говорит только о том, насколько хорошо данные описываются прямой линией.Практическое правило простое: если вы показываете тренд в отчёте, не ограничивайтесь наклоном. Добавляйте
REGR_R2, количество наблюдений и, если решение важное, обязательно смотрите на график. Тогда вместо красивой, но случайной линии у вас появится нормальная аналитическая проверка.