У меня есть таблица чисел в базе данных Postgres, и я пытаюсь вычислить диапазон (max-min) 3 предыдущих и 3 следующих строк для каждой строки.
Дана тестовая таблица:
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
дублируется. Есть ли способ улучшить запрос и удалить дубликаты? Повлияет ли дубликат на производительность? Как мне обращаться с движущимся окном, если я хочу рассчитать другие агрегаты для каждого идентификатора?
Я предложил следующий запрос для повторного использования окна, но я не уверен, что это оптимальный подход.
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;