SQL

RANK() vs DENSE_RANK() vs ROW_NUMBER() no PostgreSQL: a diferença que pega todo mundo

PG Monitoring Team May 26, 2026 6 min de leitura

Três funções do PostgreSQL parecem intercambiáveis — ROW_NUMBER(), RANK() e DENSE_RANK() — e produzem o mesmo resultado, até duas linhas empatarem. Escolher a errada nesse ponto é uma fonte clássica de rankings e relatórios sutilmente errados. Este post fixa a diferença de uma vez por todas.

Três funções de ranking, uma diferença crucial

As três são window functions: numeram linhas conforme o ORDER BY dentro do OVER(), opcionalmente reiniciando por grupo do PARTITION BY. Comportam-se de forma idêntica até duas linhas empatarem no valor de ordenação — e é nesse empate que os comportamentos se separam:

  • ROW_NUMBER() — sempre único. Empates são resolvidos de forma arbitrária. Produz 1, 2, 3, 4.
  • RANK() — linhas empatadas compartilham a posição e a próxima pula as posições consumidas. Produz 1, 2, 2, 4.
  • DENSE_RANK() — linhas empatadas compartilham a posição, sem lacuna depois. Produz 1, 2, 2, 3.

Sintaxe

RANK() OVER (
  [PARTITION BY coluna_ou_expr]
  ORDER BY coluna_ou_expr [ASC | DESC]
)

O ORDER BY define a regra do ranking; o PARTITION BY, quando presente, reinicia o ranking para cada grupo. O DENSE_RANK() e o ROW_NUMBER() têm exatamente o mesmo formato — só o comportamento no empate muda.

Veja lado a lado

SELECT
  name,
  score,
  ROW_NUMBER() OVER (ORDER BY score DESC) AS row_number,
  RANK()       OVER (ORDER BY score DESC) AS rank,
  DENSE_RANK() OVER (ORDER BY score DESC) AS dense_rank
FROM players;
namescorerow_numberrankdense_rank
Ana100111
Bruno90222
Carla90322
Diego80443

Repare no Diego, a linha logo após o empate. Bruno e Carla fizeram 90 e dividem o rank 2. O RANK() então joga o Diego para 4 — as posições 2 e 3 foram "consumidas" pelo empate. O DENSE_RANK() continua contando densamente e dá 3 ao Diego. O ROW_NUMBER() ignorou o empate e numerou direto.

Macete: RANK deixa lacunas, DENSE_RANK é denso (sem lacunas), ROW_NUMBER nunca empata.

Qual deles você realmente quer?

  • Ranking com medalhas estilo olímpicoRANK(). Dois ouros significam nenhuma prata — exatamente o comportamento de pular.
  • "Quantas faixas de preço distintas existem abaixo deste produto?"DENSE_RANK(), porque importam os níveis distintos, não as posições.
  • Top-N estrito, exatamente N linhas, empates resolvidos de forma determinísticaROW_NUMBER() com uma coluna de desempate no ORDER BY (ex.: ORDER BY score DESC, id).

Top-3 por categoria

SELECT *
FROM (
  SELECT
    product_id, category, revenue,
    DENSE_RANK() OVER (
      PARTITION BY category
      ORDER BY revenue DESC
    ) AS tier
  FROM product_sales
) t
WHERE tier <= 3;

Usar DENSE_RANK() aqui faz com que um empate triplo no primeiro lugar ainda revele as próximas faixas de receita realmente diferentes, em vez de cortar em exatamente três linhas como o ROW_NUMBER() faria. Escolha de propósito: você quer "os 3 produtos do topo" (ROW_NUMBER()) ou "produtos nas 3 maiores faixas de receita" (DENSE_RANK())? Eles diferem exatamente quando há empates.

As outras funções de ranking

A mesma família inclui mais três que vale conhecer:

  • NTILE(n) — divide as linhas ordenadas em n baldes de tamanho parecido. NTILE(4) dá quartis, NTILE(100) percentis.
  • PERCENT_RANK() — rank relativo de 0 a 1: "esta linha é melhor que 80% das demais".
  • CUME_DIST() — distribuição acumulada, a fração de linhas no nível atual ou abaixo.

Mantendo a performance em produção

Todas compartilham um custo: uma ordenação sobre a partição. Conforme os dados crescem, uma consulta de ranking sem índice passa de um sort em memória para um external merge em disco e a latência se multiplica — silenciosamente. Um índice composto que casa com (coluna_particao, coluna_ordem) deixa a janela ler já ordenado e pular o sort. O PG Monitoring sinaliza exatamente essas regressões — o mesmo SQL, de repente 5× mais lento — e aponta o índice faltante nas colunas de partição/ordenação.

Related Articles

Ready to experience better PostgreSQL monitoring?

Join thousands of teams who switched from traditional tools to PG Monitoring's AI-powered platform.

Fale conosco