Postgres Функция окна Новая таблица Сохранить - PullRequest
0 голосов
/ 20 февраля 2020

Мои данные выглядят так.

Таблица A

acccount_id | value | timestamp 
-------------------------------
a12         | 122   | jan 1
a13         | 133   | jan 1
a14         | 443   | jan 1
a12         | 251   | jan 2
a13         | 122   | jan 2
a14         | 331   | jan 2
a12         | 412   | jan 3
a13         | 323   | jan 3
a14         | 432   | jan 3

У меня есть оконная функция, которая получает скользящее среднее и добавляет столбец

select account_id, value, "timestamp", 
       avg(value) over (partition by account_id order by "timestamp") as average
from the_table
order by account_id, "timestamp";

и выводит эту таблицу.

acccount_id | value | timestamp | Average
-----------------------------------------
a12         |  122  | jan 1     | 122
a13         |  133  | jan 1     | 133
a14         |  443  | jan 1     | 443
a12         |  251  | jan 2     | 188.5
a13         |  122  | jan 2     | 222.5
a14         |  331  | jan 2     | 387
a12         |  412  | jan 3     | 261.6
a13         |  323  | jan 3     | 192.6
a14         |  432  | jan 3     | 402

Мой вопрос:

Как сохранить этот новый столбец в таблице A?

Один из способов, которым я подумал сделать это, был:

(начало псевдокода)

BEGIN;
SELECT window_function FROM table_a INTO temp
ALTER TABLE table_a RENAME TO table_old;
ALTER TABLE temp RENAME TO table_a;
DROP table_old

COMMIT;

Не могли бы вы дать мне знать, как будет выглядеть выражение postgresql?

Ответы [ 3 ]

0 голосов
/ 20 февраля 2020

Я получил это на работу.

        BEGIN;

            DROP TABLE IF EXISTS temp;
            SELECT account_id, value, TO_TIMESTAMP(timestamp, 'YYYY-MM-DD HH24:MI:SS'),   
                   avg(CAST(value as FLOAT)) over (partition by account_id order by "timestamp") as average
            INTO temp
            from volume_temp
            order by account_id, "endts";
            ALTER TABLE volume_temp RENAME TO volume_temp_old;
            ALTER TABLE temp RENAME TO volume_temp;
            DROP TABLE IF EXISTS temp;
            DROP TABLE IF EXISTS volume_temp_old;

        COMMIT;
0 голосов
/ 22 февраля 2020

После некоторой работы у меня вышеперечисленное сработало, но я фактически сделал это более нормализованным способом. Поэтому я просто создаю новую таблицу с именем vol_stats и добавляю pk из другой таблицы и называю ее fk.

Тогда вниз по течению я объединю две таблицы, а не одну большую таблицу.

Вот мой sql

        BEGIN;
            DROP TABLE IF EXISTS vol_stats;
            SELECT pk as fk, 
                   avg(CAST(volume as FLOAT)) over (partition by account_id order by "endts") as average,
                   count(endts) over (partition by account_id order by "endts") as count,
                   stddev(CAST(volume as FLOAT)) over (partition by account_id order by "endts") as standard_deviation,
                   variance(CAST(volume as FLOAT)) over (partition by account_id order by "endts") as var,
                   sum(CAST(volume as FLOAT)) over (partition by account_id order by "endts") as running_sum,
                   CAST(volume as FLOAT)/CAST(average as FLOAT) as vta 
            INTO vol_stats
            from volume_temp
            order by account_id, "endts";
        COMMIT;
0 голосов
/ 20 февраля 2020

Вы можете добавить новый столбец, а затем обновить его следующим образом:

alter table the_table add column average decimal(10, 5);

update the_table
set average = t.average
from (
    select 
        account_id, 
        "timestamp", 
        avg(value) over (partition by account_id order by "timestamp") as average
    from the_table
) t
where account_id = t.account_id and "timestamp" = t."timestamp";

Это предполагает, что (account_id, timestamp) кортежи уникальны по всей таблице.

...