Повторное использование одного и того же движущегося окна для нескольких оконных функций - PullRequest
1 голос
/ 16 апреля 2019

У меня есть таблица чисел в базе данных 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;

1 Ответ

1 голос
/ 16 апреля 2019

Вы можете использовать WINDOW предложение для сокращения вашего кода:

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 будет повторно использовать оконную раму, если вы также неоднократно ее произносите.

Связанный:

...