SQL COUNT()

A Ana vai mandar a newsletter de fim de ano da Loja Aurora por email. Antes, ela precisa de três números: quantos clientes a loja tem, quantos deles têm email cadastrado e de quantas cidades diferentes eles são. As três perguntas começam com "quantos", e quem responde todas é a mesma função: COUNT() ("contar", em inglês). Só que cada pergunta pede um jeito diferente de usá-la, e confundir os três é um dos erros mais comuns de quem começa.

Você vai aprender
  • COUNT(*): contar linhas.
  • COUNT(coluna): contar os valores preenchidos de uma coluna, pulando os NULL.
  • COUNT(DISTINCT coluna): contar os valores diferentes.
  • Como contar os que faltam (os clientes sem email).
  • As armadilhas: COUNT(vip) que conta todo mundo, COUNT('email') com aspas simples, = NULL.
  • Os erros reais do SQLite com COUNT.

Se você ainda não leu, comece por O que são Funções Agregadas: lá está a ideia de "muitas linhas entram, uma sai".


A ideia: a lista de chamada

Imagine a professora com a lista de chamada da turma. Ela pode fazer três contas diferentes:

Pergunta da professoraComo ela contaEm SQL
Quantos alunos estão na lista?Conta as linhas da lista, uma por alunoCOUNT(*)
Quantos deixaram o telefone?Conta só as linhas em que o telefone está preenchidoCOUNT(telefone)
De quantos bairros diferentes eles vêm?Conta cada bairro uma vez só, mesmo que se repitaCOUNT(DISTINCT bairro)

A Loja Aurora tem exatamente esse caso na tabela clientes: 30 clientes, 3 sem email (os de id 7, 15 e 23) e várias cidades repetidas.


1. COUNT(*): quantas linhas

O jeito mais simples: COUNT(*) conta as linhas da tabela, sem olhar o que tem dentro delas.

SELECT COUNT(*) AS clientes
FROM clientes;
COUNT
A função de contar.
(*)
O asterisco quer dizer "a linha toda". COUNT(*) conta cada linha, mesmo uma linha cheia de NULL. É a única função agregada que aceita o *.
AS clientes
Um apelido para a coluna do resultado (aula Apelidos (AS)). Sem ele, a coluna se chamaria COUNT(*).
FROM clientes
A tabela cujas linhas são contadas.

Com WHERE, o COUNT(*) conta só as linhas que passaram no filtro. Quantos pedidos tiveram frete grátis?

SELECT COUNT(*) AS frete_gratis
FROM pedidos
WHERE frete = 0;

Onze pedidos. Primeiro o WHERE separa as linhas com frete = 0, depois o COUNT(*) conta o que sobrou.

Experimente: a consulta conta todos os clientes. Acrescente um WHERE para contar só os de Teresina, a cidade da loja. Lembre: texto vai entre aspas simples.

SELECT COUNT(*) AS clientes
FROM clientes;
SELECT COUNT(*) AS clientes
FROM clientes
WHERE cidade = 'Teresina';

2. COUNT(coluna): quantos valores preenchidos

Agora a pergunta da newsletter: quantos clientes têm email? Em vez do *, ponha o nome da coluna:

SELECT COUNT(*)          AS clientes,
       COUNT(email)      AS com_email,
       COUNT(nascimento) AS com_nascimento
FROM clientes;
COUNT(*)
Conta as 30 linhas.
COUNT(email)
Conta as linhas em que email não é NULL. Os três clientes sem email ficam de fora: 27.
COUNT(nascimento)
Mesma ideia na coluna nascimento: dois clientes (9 e 21) não informaram a data, então dá 28.

A regra é uma só: COUNT(coluna) conta os valores que não são NULL. Ele não olha se o valor é bonito, se é zero ou se é um texto vazio; só pergunta "tem algo aqui ou é desconhecido?".

O mesmo truque responde "quantos pedidos já foram entregues?", porque o pedido que ainda não chegou tem entregue_em NULL:

SELECT COUNT(*)          AS pedidos,
       COUNT(entregue_em) AS entregues
FROM pedidos;

90 pedidos, 85 entregues. Os outros 5 estão a caminho.


3. Contar os que faltam

A Ana quer ligar para os clientes sem email e pedir o endereço. Quantos são? Há dois caminhos, e os dois dão 3:

SELECT COUNT(*) - COUNT(email) AS sem_email
FROM clientes;
SELECT COUNT(*) AS sem_email
FROM clientes
WHERE email IS NULL;

O primeiro faz uma conta de menos: todas as linhas menos as que têm email. O segundo filtra com IS NULL (aula IS NULL e IS NOT NULL) e conta as linhas que sobraram. O segundo é mais fácil de ler; o primeiro é útil quando você quer os dois números na mesma linha, ao lado de outras contas.


4. COUNT(DISTINCT coluna): quantos valores diferentes

A terceira pergunta: de quantas cidades são os clientes? Se você contar a coluna cidade, dá 30, porque todo cliente tem cidade. Mas Teresina aparece 10 vezes, São Paulo 7… A palavra DISTINCT ("distinto", "diferente") manda contar cada valor uma vez só:

SELECT COUNT(cidade)          AS cidades,
       COUNT(DISTINCT cidade) AS cidades_diferentes
FROM clientes;
COUNT(cidade)
30: conta as cidades preenchidas, com repetição.
COUNT(DISTINCT cidade)
8: primeiro tira as repetições (Teresina, São Paulo, Fortaleza, Recife, Parnaíba, Picos, Oeiras e Floriano), depois conta.

É o mesmo DISTINCT da aula SELECT DISTINCT, só que aqui ele trabalha dentro do COUNT. Ele responde perguntas ótimas sobre a loja:

SELECT COUNT(DISTINCT produto_id) AS produtos_vendidos
FROM itens_pedido;

A tabela itens_pedido tem 220 linhas, mas os mesmos produtos aparecem em vários pedidos. Produtos diferentes que já foram vendidos pelo menos uma vez: 42. Como a loja tem 45 produtos, três nunca foram vendidos (você vai descobrir quais na aula LEFT JOIN).

O DISTINCT também pula o NULL

Na tabela fornecedores, os dois estrangeiros (de Portugal e da Argentina) têm estado NULL. Compare a lista com a contagem:

SELECT DISTINCT estado FROM fornecedores;
SELECT COUNT(DISTINCT estado) AS estados FROM fornecedores;

A lista tem 4 linhas, uma delas NULL. A contagem dá 3. Não é contradição: o SELECT DISTINCT mostra o NULL como um valor a mais, mas o COUNT, como toda função agregada, não conta NULL. Se alguém perguntar "quantos estados aparecem na lista?", confira se a pessoa quer contar o "sem estado" ou não.


5. COUNT(*), COUNT(1) ou COUNT(id)?

Você vai ver estas três formas por aí. Numa coluna que nunca é NULL, como a chave primária id, elas dão o mesmo número:

SELECT COUNT(*), COUNT(1), COUNT(id)
FROM clientes;

COUNT(1) conta quantas vezes o número 1 "não é NULL", ou seja, uma vez por linha. Funciona, mas COUNT(*) diz melhor o que você quer ("conte as linhas") e é a forma que todo banco reconhece e otimiza. Use COUNT(*) para linhas e COUNT(coluna) só quando quiser pular os NULL daquela coluna.


6. Formas diferentes de contar os VIPs

Na tabela clientes, a coluna vip vale 1 para os clientes VIP e 0 para os outros. Quantos VIPs a loja tem? Primeiro, a armadilha:

SELECT COUNT(vip) AS vips FROM clientes;

Deu 30, a tabela inteira! O COUNT(vip) não pergunta se o valor é 1; pergunta se ele não é NULL. E o 0 não é NULL: é um valor conhecido, que quer dizer "não é VIP". Então todo mundo foi contado. As formas certas:

SELECT COUNT(*) AS vips FROM clientes WHERE vip = 1;
SELECT SUM(vip) AS vips FROM clientes;

As duas dão 5. A segunda funciona porque vip só tem 0 e 1: somar os uns é o mesmo que contar os VIPs (aula SUM()).

FormaResultadoQuando usar
COUNT(*) … WHERE vip = 15 (certo)A forma mais clara. Use esta.
SUM(vip)5 (certo)Só para colunas 0/1, quando você quer esse número ao lado de outros, na mesma linha
COUNT(vip)30 (errado)Nunca para "quantos são 1": conta tudo que não é NULL

Quando dá errado

Esqueceu os parênteses
SELECT COUNT * FROM produtos;

A mensagem: near "FROM": syntax error, "erro de sintaxe perto de FROM". Sem os parênteses, o SQLite não enxerga uma função: lê COUNT como o nome de uma coluna e o * como "vezes", e fica esperando o número da multiplicação. Quando chega o FROM, ele desiste. Repare que a mensagem aponta o FROM, e não o COUNT: o erro de sintaxe aparece onde o SQLite percebeu o problema, que às vezes é um pouco depois de onde ele está.

Como consertar: COUNT(*), com os parênteses.

Aspas simples em volta da coluna

Em vez de errar, a consulta abaixo dá um resultado errado, sem aviso nenhum:

SELECT COUNT('email') AS com_email FROM clientes;

O que aconteceu: deu 30, e não 27. Com aspas simples, 'email' é o texto "email", igual em todas as linhas, e um texto nunca é NULL. O COUNT contou 30 vezes a palavra "email".

Como consertar: nome de coluna vai sem aspas: COUNT(email). Aspas simples são só para texto. E aspas duplas? Neste editor, "email" é um nome de coluna, então COUNT("email") funciona e dá 27. Com um nome que não existe, como COUNT("e-mail"), o SQLite responde no such column: "e-mail" - should this be a string literal in single-quotes? ("não existe a coluna "e-mail"; isto devia ser um texto entre aspas simples?"). Escreva os nomes de coluna sem aspas e em minúsculas.

Contar os sem email com = NULL
SELECT COUNT(*) AS sem_email
FROM clientes
WHERE email = NULL;

O que aconteceu: deu 0, mas são 3. Qualquer comparação com NULL usando = dá "desconhecido", nunca "verdadeiro", e o WHERE só deixa passar o verdadeiro. Nenhuma linha passou, e contar nada dá zero (veja O Valor NULL).

Como consertar: WHERE email IS NULL.

DISTINCT com duas colunas

A Ana quer contar as combinações diferentes de cidade e estado:

SELECT COUNT(DISTINCT cidade, estado) FROM clientes;

A mensagem: wrong number of arguments to function COUNT(), "número errado de argumentos para a função COUNT()". No SQLite, o COUNT(DISTINCT …) aceita uma coluna só.

Como consertar: para contar combinações, conte as linhas de um SELECT DISTINCT cidade, estado, o que você aprende a fazer numa consulta só na aula Subconsultas. Ou agrupe com GROUP BY em várias colunas e veja quantas linhas saem.

Nos outros bancos
  • MySQL e MariaDB aceitam várias colunas no COUNT(DISTINCT …): COUNT(DISTINCT cidade, estado) conta as combinações diferentes que não têm NULL. No SQLite e no padrão, é uma coluna só.
  • SQL Server: COUNT devolve um int (até uns 2,1 bilhões). Para tabelas maiores existe COUNT_BIG, que devolve bigint.
  • PostgreSQL: COUNT devolve bigint.
SELECT COUNT(DISTINCT cidade, estado) FROM clientes;

Referência rápida

EscritaContaNa Loja Aurora
COUNT(*)Todas as linhas30 clientes
COUNT(coluna)As linhas em que a coluna não é NULLCOUNT(email) = 27
COUNT(DISTINCT coluna)Os valores diferentes, sem contar NULLCOUNT(DISTINCT cidade) = 8
COUNT(*) - COUNT(coluna)As linhas em que a coluna é NULL3 sem email
COUNT(*) … WHERE condAs linhas que passaram no filtroWHERE vip = 1 → 5
Sem nenhuma linhaSempre 0, nunca NULL
Mensagem do SQLiteQuer dizer
near "FROM": syntax errorFaltou o parêntese em COUNT *
wrong number of arguments to function COUNT()Mais de uma coluna dentro do COUNT(DISTINCT …)
misuse of aggregate function COUNT()COUNT dentro do WHERE (veja HAVING)

Exercícios

1. Quantos pedidos

Complete para contar todas as linhas da tabela pedidos:

SELECT COUNT() FROM pedidos;

2. Quantos têm nascimento

Complete para contar só os clientes que informaram a data de nascimento:

SELECT COUNT() FROM clientes;

3. Vendedores diferentes

Complete para contar quantos funcionários diferentes já atenderam pedidos:

SELECT COUNT( funcionario_id) FROM pedidos;

4. A coluna descontinuado vale 0 ou 1 em todos os 45 produtos, e só 2 são 1. Quanto dá SELECT COUNT(descontinuado) FROM produtos;?

5. SELECT DISTINCT estado FROM fornecedores; mostra 4 linhas (PI, CE, SP e NULL). Quanto dá COUNT(DISTINCT estado)?

6. O que devolve COUNT(*) quando o WHERE não deixa passar nenhuma linha?

Missão final: o relatório da newsletter

Missão: monte, numa linha só, o relatório que a Ana precisa: o total de clientes (clientes), quantos têm email (com_email), quantos não têm (sem_email) e de quantas cidades diferentes eles são (cidades). Use esses apelidos, nessa ordem.

SELECT COUNT(*) AS clientes
FROM clientes;
SELECT COUNT(*)                AS clientes,
       COUNT(email)            AS com_email,
       COUNT(*) - COUNT(email) AS sem_email,
       COUNT(DISTINCT cidade)  AS cidades
FROM clientes;

Resumo

  • COUNT(*) conta linhas, inclusive as que têm NULL.
  • COUNT(coluna) conta os valores que não são NULL. Zero e texto vazio contam; só o NULL fica de fora.
  • COUNT(DISTINCT coluna) conta os valores diferentes, também sem o NULL. No SQLite, uma coluna só.
  • Os que faltam: COUNT(*) - COUNT(coluna) ou COUNT(*) … WHERE coluna IS NULL. Nunca = NULL.
  • Para "quantos são 1" numa coluna 0/1, use WHERE coluna = 1 (ou SUM), nunca COUNT(coluna).
  • COUNT sem nenhuma linha dá 0. Nome de coluna vai sem aspas: COUNT('email') conta um texto, e dá o total de linhas.