递归 CTE Table - 计算 EWMA (EMA) - 如何 optimize/refactor 这段代码不会每次都被 TDWM 杀死?
Recursive CTE Table - Calculating EWMA (EMA) - How to optimize/refactor this code so it doesn't get killed by TDWM every time?
我创建了一个正在制作 CTE 表的查询,其中两个是非递归的,一个是递归的,以便计算指数加权移动平均值 (EMA)。
当我 运行 我在 Teradata 中的代码在一段时间后被 TDWM 杀死。
有什么想法可以 improve/work 解决这个问题吗?
WITH
smooth AS (
SELECT CAST(0.741870935 AS NUMERIC (20,5)) AS alpha
),
numbered AS (
SELECT
ROW_NUMBER() OVER (ORDER BY customer_name, closed_date) as rn,
customer,
closed_date,
metric
FROM my_table
),
recursive EWMA AS (
SELECT rn, customer, closed_date, metric, CAST(metric AS NUMERIC(20,5)) as EWMA
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
FROM EWMA
JOIN numbered
ON EWMA.rn + 1 = numbered.rn
CROSS JOIN smooth
)
SELECT * FROM EWMA
ORDER BY closed_date;
您是否尝试过设置一个 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;
假定 my_table
table 非常大,与 numbered
的递归连接可能会导致此问题。理想情况下,您希望对 PI 列进行直接相等连接——即 table1.pi_col1 = table2.pi_col2
。不确定使用 +1
表达式将如何影响连接。
从高层次上看您的查询,您似乎只想在当前行的计算中使用上一行的值。如果是这样,那么您可以完全取消递归 CTE,只需使用 LAG()
window 函数:
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;
我创建了一个正在制作 CTE 表的查询,其中两个是非递归的,一个是递归的,以便计算指数加权移动平均值 (EMA)。 当我 运行 我在 Teradata 中的代码在一段时间后被 TDWM 杀死。
有什么想法可以 improve/work 解决这个问题吗?
WITH
smooth AS (
SELECT CAST(0.741870935 AS NUMERIC (20,5)) AS alpha
),
numbered AS (
SELECT
ROW_NUMBER() OVER (ORDER BY customer_name, closed_date) as rn,
customer,
closed_date,
metric
FROM my_table
),
recursive EWMA AS (
SELECT rn, customer, closed_date, metric, CAST(metric AS NUMERIC(20,5)) as EWMA
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
FROM EWMA
JOIN numbered
ON EWMA.rn + 1 = numbered.rn
CROSS JOIN smooth
)
SELECT * FROM EWMA
ORDER BY closed_date;
您是否尝试过设置一个 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;
假定 my_table
table 非常大,与 numbered
的递归连接可能会导致此问题。理想情况下,您希望对 PI 列进行直接相等连接——即 table1.pi_col1 = table2.pi_col2
。不确定使用 +1
表达式将如何影响连接。
从高层次上看您的查询,您似乎只想在当前行的计算中使用上一行的值。如果是这样,那么您可以完全取消递归 CTE,只需使用 LAG()
window 函数:
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;