CREATE TABLE vouchers (
id SERIAL PRIMARY KEY,
collected_date DATE,
collected_volume INT
);
INSERT INTO vouchers
(collected_date, collected_volume
)
VALUES
('2024-03-09', '900'),
('2024-04-20', '300'),
('2024-04-20', '800'),
('2024-05-24', '400'),
('2025-01-17', '200'),
('2025-02-15', '800'),
('2025-02-15', '150');
Resultado Esperado
data_coletada | volume_coletado |
---|---|
2025-03-09 | 900 |
2024-03-09 | -900 |
2025-04-20 | 1100 |
2024-04-20 | -1100 |
2025-05-24 | 400 |
2025-05-24 | -400 |
2026-01-17 | 200 |
2025-01-17 | -200 |
2026-02-15 | 950 |
2026-02-15 | -950 |
Para ir dos dados brutos aos resultados esperados, são necessárias estas etapas:
Etapa 1: Calcule um expire_date
que é sempre 12 meses após a collected_date
Etapa 2: Coloque o expire_date
na linha abaixo do collected_date
. Não em uma coluna separada!
Etapa 3: Coloque o total collected_volume
por collected_date
como um número negativo na linha com o expire_date
.
Até agora consegui desenvolver esta consulta:
select
collected_date as collected_date,
(collected_date + interval '12 months')::date as expire_date,
sum(collected_volume) as collected_volume
from vouchers
group by 1,2
order by 1,2;
No entanto, não tenho ideia do que preciso mudar para exibir expire_date
cada um abaixo collected_date
e não em uma coluna separada.
Você tem alguma ideia de como resolver isso?
Você pode usar uma junção lateral contra um
values
construtor. Então agrupe por esses valores.Isso é melhor porque requer apenas a leitura da tabela uma vez.
db<>violino
Um resultado um pouco mais sensato seria agrupar apenas pela
values
data.Se você quiser apenas visualizar esta saída, defina a agregação em um CTE e use uma consulta de união:
Demonstração