CREATE TABLE vouchers (
id SERIAL PRIMARY KEY,
customer VARCHAR,
collected_date DATE,
balance INT
);
INSERT INTO vouchers
(customer, collected_date, balance
)
VALUES
('customer_a', '2024-03-09', '1600'),
('customer_a', '2024-04-20', '2700'),
('customer_a', '2024-05-24', '3100'),
('customer_a', '2025-03-09', '1500'),
('customer_a', '2025-04-20', '400'),
('customer_a', '2025-05-24', '0'),
('customer_b', '2024-10-17', '200'),
('customer_b', '2025-02-15', '1000'),
('customer_b', '2025-10-17', '800'),
('customer_b', '2025-11-18', '950'),
('customer_b', '2026-02-15', '1150'),
('customer_b', '2026-11-18', '0');
Resultado esperado:
cliente | data_selecionada | equilíbrio |
---|---|---|
cliente_a | 2025-03-31 | 1500 |
cliente_b | 2025-03-31 | 1000 |
No resultado esperado, quero exibir apenas o mais recente disponível balance
por customer
com base em uma determinada data.
Neste exemplo 2025-03-31
.
Até agora consegui desenvolver esta consulta:
select
customer as customer,
collected_date as collected_date,
sum(balance) as balance,
max(collected_date) over (partition by customer) AS max_date
from vouchers
where collected_date < '2025-03-31'
group by 1, 2
order by 1, 2 desc;
Ele quase me leva ao resultado correto. No entanto, não consegui fazê-lo funcionar completamente.
O que preciso mudar para obter o resultado esperado?
Você pode usar
DISTINCT ON
eORDER BY collected_date DESC
Dessa forma, você obterá apenas a linha mais recente por cliente que satisfaça sua
WHERE
cláusula.Veja este db<>fiddle com seus dados de exemplo.
Obrigado por todas as respostas, tanto diretamente quanto nos comentários.
Como são duas soluções principais, decidi resumi-las em uma resposta.
Você pode encontrar ambas as soluções neste violino: https://dbfiddle.uk/I-04TlNl
Para ambos adicionei um CTE com a data como variável.
Solução usando "distinct on" (de Jonas Metzler)
Solução usando "partition by with row_number" (de Guillaume Outters)