Я пытаюсь сделать какую-то промежуточную сумму в таблице с пробелами. У меня есть период, категория и значение, и я хочу перечислить все категории, использованные в текущем и предыдущем периодах для данного 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