Вы пробовали установить поле depth
для ограничения рекурсии? Что-то вроде:
WITH smooth AS (...),
numbered AS (...),
recursive EWMA AS (
SELECT
rn, customer, closed_date, metric, CAST(metric AS NUMERIC(20,5)) as EWMA,
1 AS depth
FROM numbered
WHERE rn = 1
UNION ALL
SELECT
numbered.rn, numbered.customer, numbered.closed_date, numbered.metric,
smooth.alpha * numbered.metric + (1-smooth.alpha) * EWMA.EWMA,
EWMA.Depth + 1 AS Depth
FROM EWMA
INNER JOIN numbered ON EWMA.rn + 1 = numbered.rn
CROSS JOIN smooth
WHERE depth <= 10 -- Restrict recursion
)
SELECT *
FROM EWMA
ORDER BY closed_date;
Рекурсивное соединение с numbered
может вызывать проблему, если таблица my_table
очень большая. В идеале вам нужно выполнить прямое соединение по равенству для столбцов PI, например table1.pi_col1 = table2.pi_col2
. Не уверен, как использование выражения +1
повлияет на соединение.
Глядя на ваш запрос с высокого уровня, кажется, что вы просто хотите использовать значение предыдущей строки в вычислении текущей строки. Если это так, то вы могли бы вообще отказаться от рекурсивного CTE и просто использовать оконную функцию LAG()
:
WITH smooth AS (
SELECT CAST(0.741870935 AS NUMERIC (20,5)) AS alpha
)
SELECT
ROW_NUMBER() OVER (ORDER BY customer_name, closed_date) as rn, -- row number
customer,
closed_date,
metric,
CAST(
COALESCE(
(smooth.alpha * metric + (1-smooth.alpha)) * -- current row's value
LAG((smooth.alpha * metric + (1-smooth.alpha))) OVER(
ORDER BY customer_name, closed_date) -- previous row's value
, metric -- handle first row (no previous "EWMA" value)
)
AS NUMERIC(20,5)) AS EWMA
FROM my_table;