为多个 window 函数重复使用相同的移动 window
Reusing the same moving window for multiple window functions
我在 Postgres 数据库中有 table 个数字,我正在尝试为每一行计算前 3 行和后 3 行的范围(最大-最小)。
给定一个测试 table:
CREATE TABLE test_table AS (
SELECT
generate_series(1,100) id,
random()*generate_series(1,100) val
);
这可以通过以下查询完成:
SELECT
id,
MAX(val) OVER (
ORDER BY id
ROWS
BETWEEN 3 PRECEDING
AND 3 FOLLOWING
) -
MIN(val) OVER (
ORDER BY id
ROWS
BETWEEN 3 PRECEDING
AND 3 FOLLOWING
) val_range
FROM test_table;
但是 OVER
子句重复了。有没有办法改进查询并删除重复项?重复会影响性能吗?如果我想为每个id计算其他聚合,我应该如何处理移动window?
我提出了以下查询来重用 window,但我不确定这是否是最佳方法。
WITH
windowed AS (
SELECT
id,
UNNEST(ARRAY_AGG(val) OVER (
ORDER BY id
ROWS
BETWEEN 3 PRECEDING
AND 3 FOLLOWING
)) val
FROM test_table
)
SELECT
id,
MAX(val)-MIN(val) val_range,
AVG(val) val_mean,
STDDEV(val) val_stddev
FROM windowed
GROUP BY id
ORDER BY id;
您可以使用 WINDOW
clause 来缩短代码:
SELECT id
, MAX(val) OVER w -
MIN(val) OVER w AS val_range
FROM test_table
WINDOW w AS (ORDER BY id ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING);
但这对性能几乎没有影响。如果您也重复拼写,Postgres 将重用 window 框架。 The manual:
When multiple window functions are used, all the window functions
having syntactically equivalent PARTITION BY
and ORDER BY
clauses
in their window definitions are guaranteed to be evaluated in a single
pass over the data.
相关:
- How to use a ring data structure in window functions
我在 Postgres 数据库中有 table 个数字,我正在尝试为每一行计算前 3 行和后 3 行的范围(最大-最小)。 给定一个测试 table:
CREATE TABLE test_table AS (
SELECT
generate_series(1,100) id,
random()*generate_series(1,100) val
);
这可以通过以下查询完成:
SELECT
id,
MAX(val) OVER (
ORDER BY id
ROWS
BETWEEN 3 PRECEDING
AND 3 FOLLOWING
) -
MIN(val) OVER (
ORDER BY id
ROWS
BETWEEN 3 PRECEDING
AND 3 FOLLOWING
) val_range
FROM test_table;
但是 OVER
子句重复了。有没有办法改进查询并删除重复项?重复会影响性能吗?如果我想为每个id计算其他聚合,我应该如何处理移动window?
我提出了以下查询来重用 window,但我不确定这是否是最佳方法。
WITH
windowed AS (
SELECT
id,
UNNEST(ARRAY_AGG(val) OVER (
ORDER BY id
ROWS
BETWEEN 3 PRECEDING
AND 3 FOLLOWING
)) val
FROM test_table
)
SELECT
id,
MAX(val)-MIN(val) val_range,
AVG(val) val_mean,
STDDEV(val) val_stddev
FROM windowed
GROUP BY id
ORDER BY id;
您可以使用 WINDOW
clause 来缩短代码:
SELECT id
, MAX(val) OVER w -
MIN(val) OVER w AS val_range
FROM test_table
WINDOW w AS (ORDER BY id ROWS BETWEEN 3 PRECEDING AND 3 FOLLOWING);
但这对性能几乎没有影响。如果您也重复拼写,Postgres 将重用 window 框架。 The manual:
When multiple window functions are used, all the window functions having syntactically equivalent
PARTITION BY
andORDER BY
clauses in their window definitions are guaranteed to be evaluated in a single pass over the data.
相关:
- How to use a ring data structure in window functions