|

Encontrando os valores mais populares de um campo no SQL Server

Compartilhe :

Uma pergunta comum no dia a dia com SQL é: “quais são os valores mais frequentes de uma coluna?” — por exemplo, as cidades com mais clientes, os produtos mais vendidos ou os status mais comuns em uma tabela de pedidos. Neste artigo mostramos como fazer isso, incluindo variações importantes que o exemplo básico não cobre, como empates e percentuais.

Exemplo básico

No exemplo abaixo, usamos o banco de exemplo pubs do SQL Server para descobrir as 5 cidades com mais autores cadastrados na tabela authors:

SELECT TOP 5 city, COUNT(*) AS number
FROM authors
GROUP BY city
ORDER BY number DESC;

Nota: a sintaxe number = count(*) (atribuição antes da expressão) é uma forma antiga do T-SQL. A forma atual e recomendada é COUNT(*) AS number, com o alias depois da expressão — mais legível e compatível com o padrão ANSI SQL.

Cuidado com empates: TOP ... WITH TIES

O TOP 5 puro simplesmente corta no quinto registro, mesmo que o 5º e o 6º tenham exatamente a mesma contagem. Se você quer garantir que nenhum “empate” com o último colocado fique de fora, use WITH TIES (é obrigatório usar ORDER BY nesse caso):

SELECT TOP 5 WITH TIES city, COUNT(*) AS number
FROM authors
GROUP BY city
ORDER BY number DESC;

Isso pode retornar mais de 5 linhas, caso haja empate na 5ª posição — o que costuma ser o comportamento desejado em rankings.

Alternativa com função de janela (DENSE_RANK)

Uma forma mais moderna e flexível de fazer o mesmo ranking — útil principalmente quando você precisa reutilizar a posição do ranking em outros cálculos, ou aplicar o ranking dentro de subgrupos (por exemplo, top 5 cidades por estado) — é usar DENSE_RANK():

SELECT city, number, posicao
FROM (
    SELECT
        city,
        COUNT(*) AS number,
        DENSE_RANK() OVER (ORDER BY COUNT(*) DESC) AS posicao
    FROM authors
    GROUP BY city
) AS ranking
WHERE posicao <= 5
ORDER BY posicao;

Diferente do TOP, o DENSE_RANK() trata empates de forma explícita: cidades empatadas recebem a mesma posição, e a próxima posição segue em sequência (sem “pular” números).

Bônus: mostrando o percentual de cada valor

Além da contagem, muitas vezes é útil saber que fatia do total cada valor representa:

SELECT
    city,
    COUNT(*) AS number,
    CAST(COUNT(*) * 100.0 / SUM(COUNT(*)) OVER () AS DECIMAL(5,2)) AS percentual
FROM authors
GROUP BY city
ORDER BY number DESC;

Ignorando valores nulos ou vazios

Se a coluna analisada permitir valores nulos ou vazios, vale filtrar antes de agrupar, para não distorcer o ranking:

SELECT city, COUNT(*) AS number
FROM authors
WHERE city IS NOT NULL AND city <> ''
GROUP BY city
ORDER BY number DESC;

Nota sobre o banco pubs

O banco de exemplo pubs, usado no exemplo original, é um banco de demonstração bem antigo (dos tempos do SQL Server 6.5/7.0). A Microsoft não o inclui mais por padrão nas instalações atuais do SQL Server — hoje os bancos de exemplo oficiais são o AdventureWorks e o WideWorldImporters, disponíveis para download no GitHub da Microsoft. A lógica das queries deste artigo, porém, é a mesma independentemente do banco usado.

Conclusão

TOP ... ORDER BY ... DESC combinado com GROUP BY resolve bem o caso básico de “quais são os valores mais frequentes”, mas vale conhecer WITH TIES para não perder empates e DENSE_RANK() quando o ranking precisa ser reaproveitado ou aplicado por subgrupo. Combinado com percentuais e filtro de nulos, esse tipo de consulta é uma ótima base para relatórios de “top N” em qualquer sistema.


Espero que esta dica tenha sido útil e tenha ajudado a aumentar seus conhecimentos sobre o SQL Server da Microsoft.

Se você gostou, compartilhe estas dicas com um amigo ou participe de nossas redes sociais. Caso queira nos incentivar a criar mais conteúdos como este, prestigie nossos anunciantes.

Um grande abraço e até a próxima dica!

Renato Sanches

Posts Similares