Vertica: повторить категорию из предыдущего периода, если она не указана в текущем - PullRequest
0 голосов
/ 05 февраля 2020

Я пытаюсь сделать какую-то промежуточную сумму в таблице с пробелами. У меня есть период, категория и значение, и я хочу перечислить все категории, использованные в текущем и предыдущем периодах для данного storage_id, даже если в текущем периоде нет значения этой категории.

Мои данные :

period|storage_id|category|value|
------|----------|--------|-----|
     1|         1|a       |foo  |
     2|         1|b       |bar  |
     3|         1|a       |bar  |
     3|         1|b       |foo  |
     1|         2|a       |foo  |
     2|         2|b       |bar  |
     4|         2|c       |foo  |

Моя цель:

period|storage_id|category|value|
------|----------|--------|-----|
     1|         1|a       |foo  |
     2|         1|a       |NULL |
     2|         1|b       |bar  |
     3|         1|a       |bar  |
     3|         1|b       |foo  |
     1|         2|a       |foo  |
     2|         2|a       |NULL |
     2|         2|b       |bar  |
     4|         2|a       |NULL |
     4|         2|b       |NULL |
     4|         2|c       |foo  |

Мне удалось сделать это, используя временную таблицу и 2 самостоятельных соединения. Есть ли более эффективный способ сделать это, например, используя оконные функции?

Воспроизводимый пример:

 CREATE LOCAL TEMPORARY TABLE tt (
        storage_id int
    ,   category varchar(255)
    ,   value varchar(255)
    ,   period int
) ON COMMIT PRESERVE ROWS;

INSERT INTO tt
SELECT 1, 'a', 'foo', 1 UNION ALL
SELECT 1, 'b', 'bar', 2 UNION ALL
SELECT 1, 'a', 'bar', 3 UNION ALL
SELECT 1, 'b', 'foo', 3 UNION ALL
SELECT 2, 'a', 'foo', 1 UNION ALL
SELECT 2, 'b', 'bar', 2 UNION ALL
SELECT 2, 'c', 'foo', 4
;

Мое несовершенное решение:

WITH
cat as (
SELECT  
    t1.category
,   t1.storage_id
,   t2.period
FROM
    tt as t1 join tt as t2
    on t1.storage_id = t2.storage_id
    and t1.period <= t2.period
GROUP BY 
    t1.category
,   t1.storage_id
,   t2.period
)
SELECT
    cat.period
,   cat.storage_id
,   cat.category
,   tt.value    
FROM cat
    LEFT JOIN tt
    ON tt.category = cat.category
    and tt.storage_id = cat.storage_id  
    and tt.period = cat.period
ORDER BY
    storage_id, period;

11 rows, 178 ms

1 Ответ

1 голос
/ 05 февраля 2020

Я хочу перечислить все категории, используемые в текущем и предыдущем периодах, даже если в текущем периоде нет значения этой категории.

Я не вижу, как иллюстрирует ваш набор результатов это потому, что вы не довели все результаты до конца.

Для задачи, которую вы описываете , следующее должно делать то, что вы хотите:

select p.period, sc.storage_id, sc.category, tt.value
from (select distinct period from tt) p join
     (select storage_id, category, min(period) as first_period
      from tt
      group by 1, 2
     ) sc
     on p.period >= sc.first_period left join
     tt
     on tt.period = p.period and
        tt.storage_id = sc.storage_id and
        tt.category = sc.category
order by p.period, sc.storage_id, sc.category;

Здесь - это дБ <> скрипка.

Я не могу понять фактическую логику c, которая выдает нужный набор результатов.

...