Как посчитать stationarity test в SQL
Содержание:
Зачем stationarity
Stationary ряд — тот, у которого статистические свойства (mean, variance) не меняются во времени. Большинство time-series методов (ARIMA, ACF/PACF, regression) требуют stationarity. На non-stationary ряду ACF медленно затухает, регрессии дают spurious результаты.
Rolling mean и std
Глазами проверяют через скользящее среднее и std. Если оба «дрейфуют» — не stationary.
SELECT
event_date,
value,
AVG(value) OVER (ORDER BY event_date ROWS BETWEEN 30 PRECEDING AND CURRENT ROW) AS rolling_mean,
STDDEV_SAMP(value) OVER (ORDER BY event_date ROWS BETWEEN 30 PRECEDING AND CURRENT ROW) AS rolling_std
FROM daily_metrics
WHERE metric_name = 'dau'
ORDER BY event_date;Постройте в дашборде: rolling_mean плавно растёт = тренд, не stationary.
Простой ADF-like чек
Augmented Dickey-Fuller — стандартный тест. В чистом SQL только приближение через регрессию Δy_t = α + ρ × y_{t-1}:
WITH base AS (
SELECT
event_date,
value,
LAG(value, 1) OVER (ORDER BY event_date) AS prev,
value - LAG(value, 1) OVER (ORDER BY event_date) AS diff
FROM daily_metrics
WHERE metric_name = 'dau'
)
SELECT
REGR_SLOPE(diff, prev) AS rho,
REGR_R2(diff, prev) AS r2,
-- Простой t-stat = rho / SE
REGR_SLOPE(diff, prev) / (STDDEV_SAMP(diff) / SQRT(COUNT(*))) AS t_stat
FROM base
WHERE prev IS NOT NULL;В строгом ADF критическое значение примерно −3 (для α=0.05). t_stat < −3 → отвергаем unit root, ряд stationary. В SQL это грубое приближение, точный ADF — в Python statsmodels.tsa.stattools.adfuller.
Что делать с non-stationary
Если тест провален или rolling stats дрейфуют:
- Differencing:
y_t − y_{t-1}часто делает stationary. - Log-transform: стабилизирует variance.
- Detrend: вычесть линейный тренд.
- Seasonal differencing:
y_t − y_{t-7}для недельной сезонности.
Differencing
SELECT
event_date,
value,
value - LAG(value, 1) OVER (ORDER BY event_date) AS first_diff,
value - LAG(value, 7) OVER (ORDER BY event_date) AS seasonal_diff_7
FROM daily_metrics
WHERE metric_name = 'dau'
ORDER BY event_date;После differencing проверьте rolling mean — должна стать стабильной.
Частые ошибки
Ошибка 1. Прыгать в ARIMA без stationarity. ARIMA автоматически делает differencing (d параметр), но если изначально не проверили — выбор d ошибочный.
Ошибка 2. Differencing раз и навсегда. Сначала first diff. Если всё ещё non-stationary — second diff. Чаще 1-2 раза достаточно.
Ошибка 3. Сравнивать rolling-mean на разных окнах. Окно 7 и 30 могут давать разные впечатления. Standardize choice.
Ошибка 4. Игнорировать сезонность. Сезонные ряды формально non-stationary в первой разностности. Нужна seasonal differencing.
Ошибка 5. Stationarity ≠ predictability. Stationary ряд может быть pure noise. Stationarity — необходимо, не достаточно.
Связанные темы
- Как посчитать autocorrelation в SQL
- Как посчитать seasonality в SQL
- Как посчитать moving-average в SQL
- Time series forecasting для аналитика
FAQ
Strict vs wide-sense stationarity?
Wide-sense (covariance stationary) — стандарт. Mean и variance не меняются, autocovariance зависит только от lag.
Какие методы тестируют?
ADF (null: unit root), KPSS (null: stationary), Phillips-Perron. Часто запускают несколько.
Differencing меняет интерпретацию?
Да. Если работаете с Δy, прогноз тоже в Δ-единицах. Кумулировать обратно.
Можно ли без stationarity?
Современные методы (Prophet, neural nets) гибче. Но ARIMA-семейство требует.
Trend и stationarity?
Linear trend → not stationary in mean. Detrend или first-diff.