Usando a Função ROW_NUMBER e Outras Funções para Gerar Resultados Sequenciais no PostgreSQL
Por Paulo RB em 05/06/2024
Quando trabalhamos com bancos de dados, muitas vezes precisamos gerar números sequenciais para nossos resultados. Isso pode ser útil para diversas finalidades, como paginação, relatórios ou simplesmente para identificar a posição dos registros. O PostgreSQL oferece várias funções que nos permitem gerar números sequenciais. Neste post, vamos explorar a função ROW_NUMBER e outras funções similares, como RANK e DENSE_RANK.
A Função ROW_NUMBER
A função ROW_NUMBER é uma das funções de janela (window functions) do PostgreSQL que atribui um número único sequencial a cada linha de um conjunto de resultados. Esse número é reiniciado para cada partição do conjunto de resultados conforme definido pela cláusula PARTITION BY.
Sintaxe:
ROW_NUMBER() OVER (
[PARTITION BY partition_expression]
ORDER BY sort_expression
)
Exemplo:
Vamos supor que temos uma tabela chamada vendas com as colunas id, vendedor, data_venda e valor_venda. Primeiro, criaremos a tabela e inseriremos alguns dados de exemplo.
Código DDL:
CREATE TABLE vendas (
id SERIAL PRIMARY KEY,
vendedor VARCHAR(50),
data_venda DATE,
valor_venda NUMERIC
);
INSERT INTO vendas (vendedor, data_venda, valor_venda) VALUES
('Carlos', '2023-01-10', 100.00),
('Carlos', '2023-01-15', 200.00),
('Carlos', '2023-01-20', 150.00),
('Ana', '2023-01-05', 300.00),
('Ana', '2023-01-12', 250.00),
('Ana', '2023-01-25', 350.00);
Agora, queremos numerar as vendas de cada vendedor por ordem de data.
Consulta SQL:
SELECT
id,
vendedor,
data_venda,
valor_venda,
ROW_NUMBER() OVER (PARTITION BY vendedor ORDER BY data_venda) AS numero_venda
FROM vendas;
Resultado:
| id |
vendedor |
data_venda |
valor_venda |
numero_venda |
| 4 |
Ana |
2023-01-05 |
300.00 |
1 |
| 5 |
Ana |
2023-01-12 |
250.00 |
2 |
| 6 |
Ana |
2023-01-25 |
350.00 |
3 |
| 1 |
Carlos |
2023-01-10 |
100.00 |
1 |
| 2 |
Carlos |
2023-01-15 |
200.00 |
2 |
| 3 |
Carlos |
2023-01-20 |
150.00 |
3 |
Outras Funções de Numeração
Além de ROW_NUMBER, o PostgreSQL oferece outras funções de janela que podem ser úteis dependendo do caso de uso: RANK e DENSE_RANK.
A Função RANK
A função RANK é similar à ROW_NUMBER, mas permite que haja empates. Quando dois registros são iguais conforme a ordem especificada, ambos recebem o mesmo valor de RANK, e o próximo valor será pulado.
Exemplo:
Consulta SQL:
SELECT
id,
vendedor,
valor_venda,
RANK() OVER (PARTITION BY vendedor ORDER BY valor_venda DESC) AS rank_venda
FROM vendas;
Resultado:
| id |
vendedor |
valor_venda |
rank_venda |
| 6 |
Ana |
350.00 |
1 |
| 4 |
Ana |
300.00 |
2 |
| 5 |
Ana |
250.00 |
3 |
| 2 |
Carlos |
200.00 |
1 |
| 3 |
Carlos |
150.00 |
2 |
| 1 |
Carlos |
100.00 |
3 |
A Função DENSE_RANK
A função DENSE_RANK é semelhante ao RANK, mas sem pular valores. Ou seja, registros iguais terão o mesmo valor de rank, mas o próximo valor será o próximo número sequencial.
Exemplo:
Consulta SQL:
SELECT
id,
vendedor,
valor_venda,
DENSE_RANK() OVER (PARTITION BY vendedor ORDER BY valor_venda DESC) AS dense_rank_venda
FROM vendas;
Resultado:
| id |
vendedor |
valor_venda |
dense_rank_venda |
| 6 |
Ana |
350.00 |
1 |
| 4 |
Ana |
300.00 |
2 |
| 5 |
Ana |
250.00 |
3 |
| 2 |
Carlos |
200.00 |
1 |
| 3 |
Carlos |
150.00 |
2 |
| 1 |
Carlos |
100.00 |
3 |
Considerações Finais
As funções de janela do PostgreSQL são poderosas ferramentas para gerar resultados sequenciais e classificar seus dados de diversas formas. A escolha entre ROW_NUMBER, RANK e DENSE_RANK depende do comportamento desejado em caso de empates nos valores de ordenação. Cada uma dessas funções oferece uma maneira única de lidar com a numeração e classificação dos resultados.
Se você ainda não utilizou essas funções, experimente aplicá-las em suas consultas e veja como elas podem simplificar e potencializar suas análises de dados.